Java自动装箱与拆箱是编译期插入valueOf()和xxxValue()方法调用的机制,非运行时行为;装箱复用缓存对象(-128~127等),拆箱遇null抛NPE,且禁止用==比较包装类。

Java 自动装箱与拆箱的双向转换,本质是编译器在编译期插入的方法调用,不是运行时动态行为,也不涉及 JVM 特殊指令。它是一套“写起来像类型自动变,实际是悄悄调方法”的机制。
装箱:基本类型 → 包装类对象
当你写 Integer i = 100;,编译器会把它重写为 Integer i = Integer.valueOf(100);,而不是 new Integer(100)(后者早已废弃)。关键点在于:
-
valueOf() 有缓存优化:对
Integer、Byte、Short、Long、Character,-128 到 127 范围内的值复用已有对象;超出范围则新建实例 -
Boolean 只有两个实例:
Boolean.TRUE和Boolean.FALSE,所有Boolean.valueOf(true)都返回同一个对象 -
Float/Double 不做缓存:每次调用
valueOf()都新建对象
拆箱:包装类对象 → 基本类型
当你写 int x = i;(其中 i 是 Integer 类型),编译器实际生成 int x = i.intValue();。注意:
- 所有拆箱操作都调用对应方法:
intValue()、doubleValue()、booleanValue()等 - 这些方法都是 final 的,不可重写,无副作用
-
null 拆箱直接抛 NullPointerException:如果
i == null,i.intValue()运行时报错
双向转换的真实触发场景
转换不是凭空发生,而是在特定上下文中由编译器识别并插入代码:
立即学习“Java免费学习笔记(深入)”;
-
赋值语句:如
Integer a = 42;(装箱)、int b = a;(拆箱) -
方法传参与返回:调用接收
Integer的方法时传入int,或返回Integer却赋给int变量 -
算术与逻辑运算:如
Integer x = 5; int y = x + 3;—— 先拆箱x,再计算,结果仍是基本类型 -
集合操作:向
List<integer></integer>添加int值(装箱),从列表取元素赋给int(拆箱)
容易踩坑的关键细节
看似方便,但几个典型问题必须清楚:
-
别用 == 比较包装类对象:
Integer a = 127, b = 127;→a == b是true(缓存复用);但Integer c = 128, d = 128;→c == d是false(不同对象) -
循环中频繁装箱可能性能差:比如
for (int i = 0; i 会创建 10 万个 <code>Integer对象 -
方法重载时可能匹配意外:若同时存在
f(int)和f(Object),传入Integer可能走Object版本,而非直觉中的int版本 - 拆箱前务必确认非 null:尤其从集合、Map 或 Optional 中取值后直接拆箱,极易引发 NPE


















