How can autoboxing cause a NullPointerException, and how do you guard against it?
answer
- Wrapper can be null; primitive cannot
- Hidden .intValue() on null = NPE
- Map.get miss returns null -> unbox NPE
- Boolean.TRUE.equals(flag) is null-safe
- Prefer primitives / getOrDefault / Optional.orElse
basics
~20 sA wrapper like Integer can be null. When you use it where a primitive is needed, the compiler inserts an unboxing call (intValue()) on that null, which throws a NullPointerException. Check for null, or use a primitive default.
solid answer
~40 sWrapper types are objects, so they can be `null`; primitives cannot. When a `null` wrapper is used in a primitive context, the compiler silently inserts an unboxing call — `null.intValue()` — which throws NullPointerException. The trap is that the throwing line looks innocent: `int x = map.get(key);` (map miss returns null), `if (flag)` where `flag` is a `Boolean`, arithmetic like `sum + nullableInteger`, or a ternary `cond ? 1 : nullableInteger` where the mixed branches force unboxing. Guards: prefer primitives so the type can't be null; null-check before unboxing; use safe defaults via `Optional.ofNullable(x).orElse(0)` or libraries' `defaultIfNull`; for booleans use `Boolean.TRUE.equals(flag)`; and be wary of `Map.get`/JDBC/JSON sources that legitimately return null wrappers. Static analysis (nullability annotations, SpotBugs) catches many of these before runtime.
go deeper
Knows that an Integer can be null and that using it as an int can throw NPE; can add a basic null check.
Can point to the inserted unboxing call as the real cause and enumerate the common sites (Map.get, Boolean conditions, arithmetic) plus standard guards.
Designs APIs to avoid the trap (primitives or Optional), uses null-safe idioms, and leans on nullability annotations/static analysis to catch it pre-runtime.
Sets org-wide conventions (nullability annotations enforced in CI, boundary types) so unbox NPEs are structurally prevented, not just caught case by case.
## Root cause: nullability mismatch A **primitive** (`int`, `boolean`, `double`...) is a raw value and can never be `null` — there is no bit pattern reserved for 'absent'. A **wrapper** (`Integer`, `Boolean`, `Double`...) is an object reference and therefore *can* be `null`. Unboxing means the compiler turns a wrapper into its primitive by calling a method on it, e.g. `someInteger.intValue()`. If `someInteger` is `null`, that is a method call on a null reference → **NullPointerException**. The danger is that *you never wrote `.intValue()`* — the compiler inserted it — so the NPE appears on a line that reads like plain assignment or math. ## The classic places it bites 1. **Collection/map lookups that can miss:** ```java Map<String,Integer> counts = new HashMap<>(); int c = counts.get("missing"); // get returns null -> null.intValue() -> NPE ``` 2. **Boolean condition from a wrapper:** ```java Boolean enabled = config.get("flag"); // may be null if (enabled) { ... } // unboxes to boolean -> NPE if null ``` 3. **Arithmetic mixing a nullable wrapper:** ```java Integer bonus = lookupBonus(); // may be null int total = base + bonus; // bonus unboxed -> NPE ``` 4. **Ternary with mixed primitive/wrapper branches** — the language *unboxes both branches to a common primitive type*: ```java Integer maybe = null; int v = condition ? 0 : maybe; // both branches typed int -> maybe unboxed -> NPE even when condition is true on some JDKs/paths ``` 5. **External sources that return wrappers:** JDBC `ResultSet.getObject`, JSON deserializers, ORM nullable columns, and reflective getters routinely hand back `null` wrappers. ## How to guard - **Prefer primitives** wherever 'absent' is not a real state. If the field genuinely can't be missing, type it `int`, not `Integer`, and the bug becomes impossible. - **Null-check before the unbox:** ```java Integer bonus = lookupBonus(); int total = base + (bonus != null ? bonus : 0); ``` - **Use a safe default helper:** ```java int c = Optional.ofNullable(counts.get(key)).orElse(0); int c2 = counts.getOrDefault(key, 0); // boxes 0 but never returns null ``` - **Booleans:** compare instead of unboxing — `Boolean.TRUE.equals(flag)` is null-safe and yields `false` for null. - **Make absence explicit** with `Optional<Integer>` at API boundaries so callers must handle it. - **Tooling:** nullability annotations (`@Nullable`/`@NonNull`) plus SpotBugs/IDE inspections flag 'unboxing of possibly-null value' before it reaches production. ## Mental model Whenever you see a wrapper used in arithmetic, a comparison with a primitive, a condition, or assignment to a primitive, ask: *can this wrapper be null here?* If yes, an unboxing NPE is one bad input away.
- Why is `Map.get` so commonly involved in unboxing NPEs?Because `get` returns `null` on a missing key, and assigning that result to a primitive (or using it in math) inserts an unbox on null. `getOrDefault` or an Optional fallback avoids it.
- Is `Boolean.TRUE.equals(flag)` better than `flag` in an if?Yes when `flag` can be null: it returns false for null instead of throwing, because `equals` is called on the non-null constant, not on the nullable wrapper.
saying these in an interview costs you the question
- Assuming the NPE points at the real cause when the inserted unbox is invisible
- Using `if (booleanWrapper)` on a value that can be null
- Believing a try/catch around math is the right fix instead of preventing null unboxing
- Thinking only Integer is affected — all wrappers including Boolean/Double are