int 和 Integer 之间无隐式类型转换,自动装箱/拆箱是编译器插入的语法糖:装箱替换为 Integer.valueOf(),拆箱替换为 intValue();仅在赋值、方法调用、表达式运算、泛型集合等必要场景触发;valueOf() 缓存 -128~127 值,但 == 比较不可靠,应使用 Objects.equals()。

int 和 Integer 之间没有真正意义上的“隐式类型转换”。所谓“自动装箱”和“自动拆箱”,是 Java 编译器在编译期插入的语法糖,本质是静态补全方法调用,不是运行时的类型推断或 JVM 的智能识别。
装箱 = 编译器悄悄加 Integer.valueOf()
当你写 Integer i = 100; 或 list.add(42); 这类代码时,javac 并不会做类型转换,而是直接替换成:
- Integer i = Integer.valueOf(100);
- list.add(Integer.valueOf(42));
反编译字节码就能看到明确的 invokestatic java/lang/Integer.valueOf 指令。它和你手写 valueOf() 完全等价,只是省了几个字符。
拆箱 = 编译器悄悄加 intValue()
只要语义上需要把 Integer 当作基本类型用,编译器就插入 intValue() 调用:
- int x = i; → 编译为 int x = i.intValue();
- if (i == 5) → 编译为 if (i.intValue() == 5)
- return i;(方法返回 int)→ 编译为 return i.intValue();
一旦 i 是 null,intValue() 就立刻抛 NullPointerException——这不是“比较失败”,而是拆箱动作本身执行失败。
只在明确场景触发,不泛滥也不自动推导
编译器只在类型契约被打破、必须补全才能通过编译的地方才插代码,典型包括:
- 赋值:int → Integer(装箱),Integer → int(拆箱)
- 方法调用:传 int 给接收 Integer 的参数(装箱),传 Integer 给接收 int 的参数(拆箱)
- 表达式运算与比较:如
a + b(a 是 Integer,b 是 int)、a == 5、三元表达式b ? 1 : "s" - 泛型集合操作:ArrayList<Integer> 的 add() 必须装箱,get() 后赋给 int 必须拆箱
缓存机制影响 ==,但不该依赖
Integer.valueOf() 对 -128 到 127 范围内的值返回缓存对象,超出则新建:
-
Integer a = 100, b = 100; →
a == b为 true(同一缓存对象) -
Integer c = 200, d = 200; →
c == d为 false(各自新建)
这是 valueOf() 的实现细节,并非语言规范保证。用 == 比较包装类永远不可靠,应改用 Objects.equals(a, b) 或显式判空后取值比较。


















