钩子:一行代码,测出你的 Java 底子
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false!!!
同样的写法,127 是 true,128 是 false。第一次见到的人都会怀疑电脑坏了。
核心:装箱和拆箱到底是什么
上篇说过 ArrayList<int> 写不了,得写 ArrayList<Integer>——集合只认对象,不认基本类型。为了不让来往搬运太麻烦,Java 提供了自动转换:
Integer x = 100; // 自动装箱:int → Integer(编译器偷偷写 Integer.valueOf(100))
int y = x + 1; // 自动拆箱:Integer → int(编译器偷偷加 x.intValue())
"自动"的意思是编译器替你写了代码——代码没少跑,只是你没看见。
正题:127 和 128 的区别在哪
秘密在 Integer.valueOf 里:Java 预先造好了 -128 到 127 这 256 个 Integer 对象,放进缓存池。
- 装箱值在 -128~127 之间:直接从池里拿,两次拿的是同一个对象 →
==比地址,true; - 超出范围:现场 new 一个新对象,两次装箱是两个对象 →
==比地址,false。

事故现场:这个坑怎么咬人
库存系统里数量用 Integer 存(能表示 null,比 int 方便),某天对账:
Integer stock1 = 128; // 从数据库查的
Integer stock2 = 128; // 从缓存查的
if (stock1 == stock2) { ... } // 缓存生效前是 false,数量永远"对不上"
测试环境数量小(< 128)一切正常,一上生产数量过千就出灵异事件。修复只要一个词:equals。
第 22 篇的口诀原样适用:== 比地址,equals 比内容。Integer 是对象,对象比较用 equals,没有例外。
第二颗雷:null 拆不箱
前面那道题的雷,现在引爆:
Map<String, Integer> price = new HashMap<>();
int p = price.get("banana"); // get 返回 null → 拆箱 → NullPointerException
get 没查到返回 null,没问题;但赋给 int 要拆箱——null 是"没有对象",拆不成 int,直接 NPE。
两颗雷一个解法:包装类型比较用 equals;跟基本类型混算之前,先判 null(或用 getOrDefault(key, 0) 给默认值)。
速查表
| 写法 | 结果 | 原因 |
|---|---|---|
Integer a=127, b=127; a==b |
true | 命中缓存池,同一对象 |
Integer a=128, b=128; a==b |
false | 超出缓存,两个对象 |
Integer 与 int 用 == |
比值(拆箱) | 但 Integer 为 null 时 NPE |
| 包装类型比较 | 永远 equals | 比内容,稳 |
map.get(key) 赋给 int |
可能 NPE | null 拆不箱,先判空 |
本文示例代码均已本地实测通过,可直接运行。
对应文件:BoxingDemo.java
橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。