Unboxing is Java’s implicit conversion from a wrapper object such as Integer, Double, or Boolean to its primitive value. Conceptually, Java calls an instance method such as doubleValue(). That hidden call matters because unboxing null throws NullPointerException. section 2.6.1 section 5.1.1
A common trap is a conditional expression with one boxed numeric branch and one primitive branch. The primitive type can win during type selection, forcing the boxed branch to unbox; the final primitive result may then be boxed again for a boxed return type. Thus valueOrZero(true, null) throws rather than returning null. section 2.6.1
Double valueOrZero(boolean condition, Double value) {
return Double.valueOf(
condition ? value.doubleValue() : 0.0);
}
Making the implicit conversions explicit reveals both the null-sensitive doubleValue() call and the final reboxing. section 2.6.1
Nested ternaries make the type calculation still harder to see. A seemingly valid Integer result containing 2, 1, or null can unbox null in one ordering of conditions, while a reordered version can avoid unboxing because it resolves to Integer instead. Do not infer safety from the declared return type alone. section 2.6.2
Prefer designs that make nullability and alternatives explicit:
- Convert boxed numeric values to primitives early when null is not meaningful; this makes the non-null requirement visible. section 2.6.1
- Replace numeric ternaries—especially nested ones or branches of different types—with if statements. section 2.6.1 section 2.6.2
- Do not use a nullable Boolean to represent a third outcome such as Cancel; use an enum and switch so callers must handle every outcome. section 5.1.1
- Validate API inputs with requireNonNull() when null is not accepted. section 5.1.1
Nullable Boolean at an if condition
Changing a two-outcome decision from boolean to Boolean so that null means Cancel preserves compilation at existing if call sites. When Cancel occurs, the if condition automatically unboxes null and throws NullPointerException. An enum such as YES, NO, CANCEL makes the additional state explicit and supports a switch-based decision. section 5.1.1
Static analysis can identify some unboxing hazards, but coverage differs. IntelliJ IDEA reports a possible exception from unboxing, and PVS-Studio has an automatic-unboxing warning; SonarLint may instead flag nested ternaries and miss the remaining null-unboxing risk after refactoring. section 2.6.2
Unboxing also changes which comparison operation is used. Double.equals() distinguishes boxed +0.0 and -0.0, whereas comparing a Double with primitive -0.0 unboxes the Double and yields primitive comparison behavior. This can expose signed-zero differences in collections and generated record equality. section 4.15.1
