自动拆箱本质是调用包装类的xxxValue()方法,对null调用会抛出NullPointerException;常见隐式拆箱场景包括==比较、算术运算、三目运算、mapToInt及取值赋值等。

因为自动拆箱本质是调用包装类的方法,而对 null 对象调用任何实例方法都会抛出 NullPointerException。
拆箱不是“转换”,而是“方法调用”
当你写下:
Integer num = null;
int value = num;
编译器会把它翻译成:
int value = num.intValue();
而 num 是 null,所以这行等价于在 null 上调用 intValue() —— Java 规定这是非法操作,立刻触发 NPE。
哪些地方会悄悄触发拆箱?
你未必写了 .intValue(),但这些写法全都会隐式拆箱:
-
if (num == 5)→ 先把num拆成int再比较 -
int x = num + 1→ 必须先拆箱才能做算术 -
boolean flag = num != null ? num > 10 : false→ 三目中num > 10需要拆箱 -
list.stream().mapToInt(x -> x).sum()→mapToInt内部对每个元素调用intValue() -
List<integer> list = new ArrayList(); list.add(null); int a = list.get(0);</integer>→ 取出 null 后立即拆箱
为什么 String 或数组的 null 不一定炸?
因为它们不涉及自动拆箱:
-
String s = null; s.toUpperCase()→ 确实会 NPE(直接调用方法) -
if (s == null || s.length() > 0)→ 短路求值,s.length()根本不执行 -
StringUtils.isEmpty(s)→ 工具方法内部先判空,安全 - 而
Integer的拆箱没有“短路”机制,只要表达式需要基本类型值,就一定会调用xxxValue()
根本原因:基本类型不能为 null
int 是栈上分配的纯数值,它没有“空”的概念。Java 设计者强制要求:要把 Integer 转成 int,就必须有确定的数值。当源头是 null,这个前提被打破,JVM 只能报错终止,而不是返回某个默认值(比如 0)——那是开发者该决定的逻辑,不是语言该越俎代庖的。

















