Skip to content
  • Wrapper Classes, Autoboxing & the Integer Cache · Java

Wrapper Classes, Autoboxing & the Integer Cache

LearnViaNotes @learnvianotes· 2 min read

Each primitive has an immutable wrapper class so it can live where objects are required (collections, generics, null). The compiler converts between them automatically — sometimes with surprising results.

PrimitiveWrapperCache (valueOf)
byteByteall values
shortShort−128 … 127
intInteger−128 … 127 (upper bound tunable)
longLong−128 … 127
charCharacter0 … 127
booleanBooleanTRUE / FALSE
float / doubleFloat / Doublenone
Java
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(5);                  // autoboxing: Integer.valueOf(5)
        int first = list.get(0);      // unboxing: list.get(0).intValue()
        Integer total = 0;
        for (int i = 1; i <= 3; i++) total += i;   // unbox, add, box again each time
        System.out.println(first + " " + total);
        System.out.println(Integer.parseInt("123") + 1);       // String → int
        System.out.println(Integer.valueOf("123").getClass().getSimpleName());
        System.out.println(Integer.toBinaryString(10) + " " + Integer.toHexString(255));
        System.out.println(Character.isDigit('7') + " " + Character.toUpperCase('q'));
    }
}
Output
5 6
124
Integer
1010 ff
true Q

The Integer cache trap

Integer.valueOf returns cached objects for −128…127. == on wrappers compares references, so it “works” for small numbers and breaks for bigger ones.

Java
public class Main {
    public static void main(String[] args) {
        Integer a = 127, b = 127;
        Integer c = 128, d = 128;
        System.out.println(a == b);          // same cached object
        System.out.println(c == d);          // two different objects
        System.out.println(c.equals(d));     // compare values
        System.out.println(c.intValue() == d);  // one side primitive → unboxes → value compare
    }
}
Output
true
false
true
true

NullPointerException from unboxing

Java
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> stock = new HashMap<>();
        stock.put("apple", 3);
        try {
            int bananas = stock.get("banana");   // get → null → null.intValue()
            System.out.println(bananas);
        } catch (NullPointerException e) {
            System.out.println("NPE while unboxing");
        }
        int safe = stock.getOrDefault("banana", 0);
        System.out.println(safe);
    }
}
Output
NPE while unboxing
0

Performance cost

  • Each boxed value is a separate heap object (~16 bytes vs 4 for an int), plus the reference.

  • Summing into a Long inside a loop creates millions of garbage objects — use a primitive long.

  • Prefer int[] over List<Integer> and IntStream over Stream<Integer> for heavy numeric work.

What does Integer a = 1000, b = 1000; a == b print, and why?

Why do we need wrapper classes?

Can the Integer cache range be changed?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report