Wrapper classes & autoboxing
Integer, Double and friends, parsing, autoboxing/unboxing, caching and null pitfalls.
Java has two worlds of types: the eight primitives (int, double, boolean...) and objects. Many APIs, especially collections and generics, only work with objects. Wrapper classes bridge the gap: each primitive has a matching class that wraps a single value in an object.
The eight wrappers#
All wrappers live in java.lang (no import needed), are immutable, and are final.
Why wrappers exist#
Wrappers are needed for:
- Collections and generics:
List<Integer>,Map<String, Double>. - Nullability: an
Integercan benull("unknown"), anintcannot. Database columns that allow NULL map naturally to wrappers. - Utility methods and constants: parsing, conversions,
MIN_VALUE/MAX_VALUE.
Autoboxing and unboxing#
Since Java 5 the compiler converts automatically:
- Autoboxing: primitive → wrapper (
Integer x = 5;becomesInteger.valueOf(5)). - Unboxing: wrapper → primitive (
int y = x;becomesx.intValue()).
It is convenient, but each box is a real object on the heap, which matters in tight loops.
Parsing and converting#
The wrappers are the standard way to turn text into numbers and back:
Note that parseInt("12.5") fails: an int has no fractional part. Use Double.parseDouble for decimals.
Useful constants and helpers#
Integer.compare is especially useful when writing comparators (see the Comparable vs Comparator lesson). Never compare with subtraction (a - b), which can overflow.
Trap 1: == on wrappers#
== on two wrapper objects compares references, not values. To save memory, Integer.valueOf (and therefore autoboxing) caches values from -128 to 127:
This bug passes tests with small numbers and fails in production with big ones. Always compare wrapper objects with equals() (or unbox them first).
Trap 2: unboxing null#
Whenever a wrapper might be null, check before using it as a primitive, or use defaults like getOrDefault.
Trap 3: performance in loops#
Changing Long total to long total makes this loop several times faster and avoids creating millions of objects. Use primitives for local arithmetic, and wrappers only where an object is required.
Trap 4: overloading with boxing#
List<Integer> has both remove(int index) and remove(Object o):
Overload resolution prefers an exact primitive match over autoboxing, so remove(1) means index 1.
Primitive or wrapper?#
Common mistakes#
- Comparing
Integers with==. - Unboxing a possibly-null wrapper.
- Using
Integer/Longfor loop counters and accumulators. new Integer(5): these constructors are deprecated for removal. UseInteger.valueOf(5)or autoboxing.
What's next#
You have seen List<Integer> and Map<String, Integer>. The angle brackets are generics: type parameters that make classes and methods reusable and type-safe. That is our next lesson.
Check your understanding
Quick quiz
1.Why can't you write
List<int>?2.What does this print?
Integer a = 1000, b = 1000; System.out.println(a == b);3.What happens when you run
Integer count = null; int n = count;?
Finished reading?
Mark this lesson complete to track your progress.