Autoboxing & Unboxing
What Is Autoboxing?
Autoboxing is the compiler automatically converting a primitive value into its corresponding wrapper object wherever an object is required. You write ordinary-looking code with primitives, and the compiler quietly wraps them for you.
Autoboxing in action
import java.util.List;
import java.util.ArrayList;
public class AutoboxingDemo {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(10); // int 10 is autoboxed to Integer.valueOf(10)
numbers.add(20);
numbers.add(30);
System.out.println(numbers);
}
}[10, 20, 30]
What Is Unboxing?
Unboxing is the reverse process — the compiler automatically extracts the primitive value out of a wrapper object wherever a primitive is expected.
Unboxing in action
import java.util.List;
import java.util.ArrayList;
public class UnboxingDemo {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
Integer boxedFirst = numbers.get(0);
int total = boxedFirst + numbers.get(1); // unboxed to add as ints
System.out.println(total);
}
}30
The Classic Trap: Unboxing null
A broken example
public class UnboxingNpeDemo {
public static void main(String[] args) {
Integer count = null; // e.g. never set from a database lookup
int total = count + 1; // unboxing null throws NPE!
System.out.println(total);
}
}Performance Cost in Tight Loops
Autoboxing is convenient, but it is not free. Every time a primitive is boxed, Java may need to allocate a new wrapper object on the heap. In a loop that runs millions of times, this can create millions of short-lived objects, adding real overhead and extra pressure on the garbage collector.
Autoboxing inside a hot loop
public class BoxingOverheadDemo {
public static void main(String[] args) {
Long sum = 0L; // wrapper type instead of primitive long
for (long i = 0; i < 1_000_000; i++) {
sum += i; // unbox sum, add, re-box the result — every iteration
}
System.out.println(sum);
}
}The Integer Cache Gotcha
Same code, different results
public class IntegerCacheDemo {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true — both from the cache
Integer x = 200;
Integer y = 200;
System.out.println(x == y); // false — two separate objects!
}
}true false