java自动装箱与拆箱是编译器在编译期插入valueof()和xxxvalue()调用实现的,非运行时魔法;javap -c反编译可清晰验证所有装箱对应valueof()、拆箱对应intvalue()等,且严格遵循“先拆、再算、后装”逻辑。

Java 中自动装箱与拆箱不是运行时魔法,而是编译器在编译阶段就完成的代码改写。要真正看清它怎么工作,最直接的方式就是用 javap -c 反编译字节码,观察编译器插入了哪些方法调用。
用 javap -c 查看装箱拆箱的真实字节码
写一段含自动装箱和拆箱的 Java 代码,例如:
public class BoxDemo {
public static void main(String[] args) {
Integer a = 100; // 装箱
int b = a; // 拆箱
Integer c = b + 1; // 先拆(隐式)、再算、再装
}
}
编译后执行:
javac BoxDemo.java javap -c BoxDemo
你会在输出中看到类似这些关键指令:
-
iconst_100→ 把整数 100 压入操作数栈 -
invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;→ 明确调用Integer.valueOf(),这就是装箱 -
invokevirtual #3 // Method java/lang/Integer.intValue:()I→ 明确调用intValue(),这就是拆箱 - 后续加法运算前,
b + 1实际是:先a.intValue()拆出int,再iadd,最后又调一次valueOf()装回Integer
反编译能帮你确认三件事
- 所有自动装箱都对应
valueOf()调用,不是new; - 所有自动拆箱都对应
xxxValue()调用(如intValue()、doubleValue()); - 编译器不会“省略”转换——哪怕只写
if (obj == 5),也会先对obj拆箱,再做数值比较。
注意两个常见干扰点
- 不要用 IDE 的“反编译插件”看
.class,它们常做二次美化,可能隐藏真实指令;必须用 JDK 自带javap -c; - 如果源码里用了
new Integer(10),字节码里会出现new+invokespecial,和valueOf()完全不同——这正是为什么new已被弃用:它绕过缓存,且语义不一致。
结合缓存行为一起验证更扎实
比如把 Integer a = 127; Integer b = 127; 和 Integer c = 128; Integer d = 128; 都写进去,再用 javap -c 看——你会发现字节码完全一样(都是 valueOf),但运行时 a == b 为 true、c == d 为 false,这就把“编译期统一处理”和“运行期对象复用”的分工清晰分开了。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











