自动装箱发生在基本类型用于需对象的上下文时(如赋值给包装类、加入集合),调用valueof()且有缓存;拆箱发生在包装类用于需基本类型的上下文时(如赋值给基本类型、算术运算),调用xxxvalue(),null时抛npe;==比较引用,建议用objects.equals。

Java 的自动装箱和拆箱是编译器在背后自动完成的类型转换,让基本类型和包装类之间“看起来无缝切换”,但实际行为有明确规则和潜在风险。
什么时候会发生自动装箱
当基本类型出现在**需要对象的上下文**中时,编译器自动调用对应包装类的 valueOf() 方法:
- 赋值给包装类变量:
Integer i = 100;→ 实际执行Integer i = Integer.valueOf(100); - 添加到集合中:
List<integer> list = new ArrayList(); list.add(42);</integer> - 作为泛型方法或构造函数参数传递(如
Optional.of(5))
注意:valueOf() 有缓存机制——Integer 对 -128 到 127 范围内的值返回复用对象;超出范围则每次新建实例。
什么时候会发生自动拆箱
当包装类对象出现在**需要基本类型的上下文**中时,编译器自动调用 xxxValue() 方法:
- 赋值给基本类型变量:
int n = i;→ 实际执行int n = i.intValue(); - 参与算术运算:
Integer a = 5; Integer b = 10; int sum = a + b; - 用于条件判断:
if (flag) { ... }(其中flag是Boolean类型)
⚠️ 拆箱最危险的点是:如果包装类变量为 null,调用 xxxValue() 会直接抛出 NullPointerException。
== 比较时的常见陷阱
== 在包装类间比较的是引用地址,不是数值:
-
Integer x = 100, y = 100;→x == y为true(共享缓存对象) -
Integer m = 200, n = 200;→m == n为false(各自新建对象) -
Integer p = 100; int q = 100;→p == q为true(p自动拆箱后比较值)
安全做法是统一用 Objects.equals(a, b),它能正确处理 null 和值比较。
性能与使用建议
高频场景下,装箱/拆箱会带来对象创建开销和 GC 压力:
- 避免在循环中反复装箱:
for (int i = 0; i - 对大量数值计算,优先使用原始类型(如
int[]而非List<integer></integer>) - 日志、格式化等隐式装箱场景(如
log.info("count: {}", count)),确认count类型是否必要为包装类 - 明确意图时,可手动调用
valueOf()或xxxValue(),增强可读性与可控性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











