What exactly are autoboxing and unboxing in Java, and where does the compiler insert them for you?
Autoboxing is the compiler converting a primitive value into its wrapper object; unboxing is the reverse. Neither conversion exists in the bytecode as an operator — the compiler desugars them into static factory calls and instance method calls, so Integer x = 5; becomes Integer x = Integer.valueOf(5); and int y = x; becomes int y = x.intValue();.
The compiler inserts these conversions in three places. Assignments and initialisations, as above. Method invocation, when the argument type and the parameter type differ only by boxing: passing an int to a method that takes an Integer boxes it, and passing an Integer to a method that takes an int unboxes it. And the compound-assignment operators, where x += 1 on a wrapper is compiled as x = x + 1 and therefore unboxes, boxes again and reassigns.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
int raw = 7;
List<Integer> counts = new ArrayList<>();
counts.add(raw); // autoboxing: int -> Integer
int back = counts.get(0); // unboxing: Integer -> int
System.out.println("round trip : " + back);
Integer boxed = 42; // autoboxing on assignment
int unboxed = boxed; // unboxing on assignment
System.out.println("assignment : " + unboxed);
// Compound assignment unboxes, adds, then boxes again.
Integer counter = Integer.valueOf(0);
counter += 5;
System.out.println("counter += 5 : " + counter);
// Which overload gets picked also depends on boxing.
System.out.println("overload : " + describe(7));
System.out.println("overload : " + describe(Integer.valueOf(7)));
}
static String describe(int value) { return "int overload"; }
static String describe(Integer v) { return "Integer overload"; }
}The overload case is the sneaky one: because both int and Integer overloads exist, the compiler chooses the primitive version for an int argument and the wrapper version for an Integer argument, with no ambiguity error. That is why an API with both overloads behaves differently depending on whether the caller boxed the value.