HuntExams Academy logo
JavaIntermediate#fundamentals

What is autoboxing and unboxing?

Answer

Automatic conversion between primitives and wrapper types (int ↔ Integer). Convenient but can cause subtle bugs (NPE on unboxing null, performance overhead in loops).

Example

Integer boxed = 10;      // autoboxing
int primitive = boxed;   // unboxing
Integer n = null;
int x = n; // throws NullPointerException at unboxing

Detailed explanation

Autoboxing is Java’s automatic conversion of a primitive value into its corresponding wrapper type, such as int to Integer, while unboxing converts a wrapper back to a primitive. Introduced in Java 5, these features reduce conversion code when primitive values interact with APIs that require objects. Each primitive has a corresponding wrapper, including Boolean, Character, and Double. For example, Integer boxed = 10; performs autoboxing, and int primitive = boxed; performs unboxing. The conversion does not make primitives objects; it bridges two distinct kinds of types.

Under the hood, the compiler inserts the appropriate conversion operations. For Integer boxed = 10;, it typically generates a call equivalent to Integer.valueOf(10). For int primitive = boxed;, it generates the equivalent of boxed.intValue(). Boxing also occurs when adding an int to a List<Integer>, because generic type arguments cannot be primitive types. Unboxing occurs in arithmetic, such as boxed + 1, and when a wrapper is passed to a method expecting its primitive counterpart. Wrappers are immutable, so incrementing an Integer involves unboxing, arithmetic, and boxing the result rather than modifying the original object.

The most important correctness risk is unboxing null. Integer n = null; is valid, but int x = n; throws NullPointerException because the conversion requires calling a method on n. Comparisons also need care: == between two Integer references compares object identity, whereas comparing an Integer with an int triggers unboxing and compares numeric values. Integer.valueOf caches values from -128 through 127, and implementations may cache more, so reference comparisons can misleadingly appear to work. Use equals for wrapper value comparison or Objects.equals when nulls are possible.

Boxing can also affect performance through allocations, reference storage, and garbage-collection pressure, although caching and JVM optimisations may eliminate some costs. Repeated boxing in large loops or numeric collections deserves attention; primitive arrays or primitive streams can be useful alternatives. Interviewers usually expect both the convenience and the trade-offs: explain the compiler-generated conversions, identify hidden null failures, distinguish identity from value equality, and avoid claiming that every boxing operation creates a new object.

Key points to remember

  • Autoboxing converts primitives to wrappers; unboxing converts wrappers to primitives.
  • The compiler inserts conversions such as Integer.valueOf(value) and wrapper.intValue().
  • Collections such as List<Integer> store wrapper references, not primitive int values.
  • Unboxing a null wrapper throws NullPointerException, including during arithmetic or comparison with a primitive.
  • Boxing may add allocation and garbage-collection costs, while wrapper == comparisons test identity.

Common mistakes candidates make

  • Assuming a null wrapper converts to a primitive default value such as zero.
  • Using == to compare two wrapper values because tests with small cached Integers happened to pass.
  • Ignoring boxing in frequently executed numeric code, or claiming every boxing conversion allocates a new object.

Likely follow-up questions

Why can Integer comparisons using == produce surprising results?

Two Integer references compared with == are checked for identity, not numeric equality. Cached instances can share identity, so use equals or null-safe Objects.equals when comparing wrapper values.

How can you safely convert a nullable Integer to int?

Handle null explicitly, for example: int value = boxed != null ? boxed : 0;. Choose a default only when it fits the application; otherwise, reject the missing value explicitly.

Does method overloading prefer primitive widening or boxing?

For overloads process(long) and process(Integer), calling process(10) selects process(long). Java considers applicable methods using primitive widening before considering methods that require boxing.

Interview tip: Start with the int-to-Integer example, explain the inserted method calls, and finish with null-unboxing and wrapper-equality pitfalls.

Related Interview Questions

1
JavaIntermediate#collections

What is the difference between Comparable and Comparator?

Open
2
JavaAdvanced#jvm

What is reflection in Java?

Open
3
JavaIntermediate#generics

What are Java generics?

Open