Lesson 9 / 38

Wrapper Classes & Autoboxing

Meet the object wrapper for every primitive, see how autoboxing/unboxing convert between them automatically, and learn the classic == pitfall with boxed Integers.

A wrapper for every primitive

int→Integer, double→Double, boolean→Boolean, char→Character, and so on. Wrappers are full objects: they can be null, stored in collections (which only hold objects), and carry useful statics like Integer.MAX_VALUE and Integer.parseInt(...).

Autoboxing & unboxing

The compiler silently converts primitive ↔ wrapper where needed — into a List<Integer>, or back out of one into an int. Convenient, but each boxing operation allocates an object, which matters in tight loops.

List<Integer> nums = new ArrayList<>();
nums.add(5);            // autobox: int -> Integer
int first = nums.get(0); // unbox: Integer -> int

Integer boxed = null;
// int bad = boxed;     // NullPointerException at unboxing!

The Integer == trap

Java caches boxed Integer values from -128 to 127, so small ones can compare equal with == by accident while larger ones don't. This is an implementation detail, not a guarantee — always use .equals() (or unbox to int) to compare wrapper values.

Integer a = 100, b = 100;
System.out.println(a == b);   // true  (cached)

Integer x = 200, y = 200;
System.out.println(x == y);   // false (not cached!)
System.out.println(x.equals(y)); // true — always correct

Quick check

Quick check: What is the safest way to compare two Integer objects for equal value?

  • == always works for Integer
  • .equals(), or unbox both to int first
  • compareTo() only, never equals()
  • They can never be compared
Answer

.equals(), or unbox both to int first — == compares references and only accidentally works for the small cached range (-128..127). .equals() (or comparing primitive int values) is always correct.