自动拆箱会引发NullPointerException,而非自动装箱;当包装类为null时,赋值给基本类型、算术运算、if条件判断、==比较、传入基本类型参数等操作均会触发隐式拆箱而崩溃。

自动装箱本身不会引发 NullPointerException,真正危险的是自动拆箱——当包装类引用为 null 时,JVM 会尝试调用 intValue()、booleanValue() 等实例方法,而 null 无法响应任何方法调用,直接抛出 NPE。面试中常考的不是“会不会”,而是“在哪踩坑”和“怎么防”。
哪些操作会悄悄触发拆箱?
这些写法看似自然,实则隐含拆箱,一旦对象为 null 就崩溃:
-
赋值给基本类型:如
Integer a = null; int b = a; -
参与算术运算:如
Integer x = null; int z = x + 10; -
用在 if 条件中:如
Boolean flag = null; if (flag) { } -
与基本类型用 == 比较:如
Integer a = null; if (a == 0) { } -
传入只接受基本类型的参数:如
Math.max(a, 5)(a 是 null 的 Integer)
最实用的防御写法
不靠运气,靠明确控制:
-
显式判空 + 默认值:用三元运算符最直白,如
int value = (num != null) ? num : 0; -
Java 9+ 推荐 Objects.requireNonNullElse:语义清晰且一行搞定,如
int value = Objects.requireNonNullElse(num, 0); -
用 Optional 封装可能为空的值:尤其适合方法返回值,如
Optional<integer> opt = Optional.ofNullable(map.get("key")); int v = opt.orElse(0);</integer> -
布尔类型特别处理:避免
if (flag),改用if (Boolean.TRUE.equals(flag))或if (Objects.nonNull(flag) && flag)
从源头减少 null 包装类
预防胜于补救:
立即学习“Java免费学习笔记(深入)”;
- 方法返回值优先用基本类型,除非需要表达“缺失”语义(比如数据库查不到某字段)
-
DTO/VO 中慎用包装类字段;必要时配合 Jackson 的
@JsonSetter(nulls = Nulls.SKIP)或 MyBatis 的nullValue="0"配置默认值 -
集合取值前先校验:如
Integer item = list.get(i); if (item != null) process(item); -
数据库查询加 COALESCE:SQL 层兜底,例如
SELECT COALESCE(age, 0) FROM user;
工具与习惯辅助
让问题在运行前暴露:
- IDE 开启装箱/拆箱警告:IntelliJ 中启用 “Boxing/unboxing of primitive types” 检查
-
自定义工具方法复用:如
NumberUtils.toInt(Integer i, int def),避免重复判空 -
静态检查注解辅助:用
@NonNull标记入参或返回值,配合 SpotBugs 或 Lombok 的@Contract提前发现风险


















