Autoboxing and Unboxing in Java

Naveen AnamaneniUpdated · 4 min read

Before Java 5, putting a number in a list meant writing list.add(Integer.valueOf(91)), and reading it back meant list.get(0).intValue(). Now you just write list.add(91) and int m = list.get(0). Autoboxing is the compiler converting a primitive to its wrapper automatically; unboxing is the reverse. It's convenient, but the conversions are still there in the bytecode, with a cost and a trap.

Boxing and Unboxing in Action

Boxing.java▶ Try it
import java.util.ArrayList;
import java.util.List;
 
public class Boxing {
    public static void main(String[] args) {
        List<Integer> marks = new ArrayList<>();
        marks.add(91);
        int first = marks.get(0);
        Integer bonus = 5;
        int total = first + bonus;
        System.out.println(total);
    }
}
Output
96

How it works

  1. marks.add(91): the list needs an Integer, so 91 is boxed.
  2. int first = marks.get(0): the Integer is unboxed to an int.
  3. Integer bonus = 5: boxing again.
  4. first + bonus: arithmetic needs primitives, so bonus is unboxed.

What the Compiler Really Writes

javap -c shows the hidden method calls:

javap -c Boxing (trimmed)
        11: invokestatic  #10                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        30: invokevirtual #26                 // Method java/lang/Integer.intValue:()I
        35: invokestatic  #10                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        41: invokevirtual #26                 // Method java/lang/Integer.intValue:()I

Boxing is Integer.valueOf(x); unboxing is x.intValue(). That's all autoboxing is: the compiler writing these calls for you.

Where Conversions Happen

SituationConversion
Assigning a primitive to a wrapper: Integer x = 5;Boxing
Passing a primitive where an object is expected: list.add(5)Boxing
Arithmetic or comparison with <, >: x + 1, x > 3Unboxing
Assigning a wrapper to a primitive: int y = x;Unboxing
x++ on an IntegerUnbox, add, box a new Integer
A ternary mixing int and IntegerOften unboxes the wrapper

The null Traps

Unboxing a null wrapper calls a method on null. The most common case is reading a missing key from a map:

Npe.java
import java.util.HashMap;
import java.util.Map;
 
public class Npe {
    public static void main(String[] args) {
        Map<String, Integer> marks = new HashMap<>();
        marks.put("Navika", 91);
        int m = marks.get("Advitha");
    }
}
Terminal output
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null
    at Npe.main(Npe.java:8)

marks.get("Advitha") returns null, and assigning it to an int calls intValue() on it. The helpful message names the exact call. Fixes: marks.getOrDefault("Advitha", 0), or keep the result as an Integer and check it.

A sneakier version hides in the conditional operator: Integer applied = member ? 10 : discount; throws when discount is null, because the mix of int and Integer makes the whole expression an int, which unboxes discount.

Common Mistakes

Unboxing a value that might be null. Check first, or use getOrDefault.

Using wrapper types for loop counters and sums. Use int and long.

Comparing two Integer objects with ==. Boxing doesn't make == compare values (see "Integer Cache in Java").

Interview Corner

What are autoboxing and unboxing?

Autoboxing is the automatic conversion of a primitive to its wrapper object, such as int to Integer, when an object is required. Unboxing is the reverse, when a primitive is required. The compiler implements them with calls to valueOf and intValue-style methods. They were introduced in Java 5.

Can unboxing cause a NullPointerException?

Yes. Unboxing calls a method such as intValue() on the wrapper, so if the wrapper is null, a NullPointerException is thrown. Common sources are map.get for a missing key and conditional expressions that mix primitives and wrappers.

Practice

  1. Easy: Store five scores in a List<Integer>, then add them up into an int total using a for-each loop. Which lines box and which unbox?
  2. Harder: Fix Npe.java two ways: with getOrDefault, and by keeping the result as an Integer and printing "not found" when it's null.

Quick check: Autoboxing

4 questions
1Which method does the compiler call to box an int?
2int m = map.get("missing"); where the map has no such key. Result?
3In Integer x = 5; x++;, what happens?
4Why avoid Long sum in a big loop?

Key Takeaways

Was this tutorial helpful?

Lesson 160 of 482