适用读者:被
Integer比较坑过的人。
前置:S04-B01。
实测环境:OpenJDK 21.0.12.1(2026-11-05)。
覆盖旧文:A-1698(265) A-1704(79) A-1762(136) A-1692(85) A-1760(263) A-1780(55) A-811(72) + 时间 API 4 张(59) = 1,014 点。
覆盖扩展:E-S04-003(Integer 缓存)、E-S04-004(值传递)。
上一篇:S04-B01 · Java 的定位、版本与"一次编写"到底怎么实现
下一篇:S04-B03 · 流程控制与运算符。
1. 一句话结论
== 比较的是"值"还是"引用",取决于两边是不是基本类型;而装箱让"看起来是值比较"的代码实际上在比较引用——这就是 127 与 128 的差别来源。
实测(JDK 21):
127==127: true
128==128: false
1000==1000: false
new Integer(127)==127: true
new==new(127): false equals: true
2. 为什么 127 相等、128 不相等(E-S04-003)
原因:Integer.valueOf(int) 有一个缓存(默认 −128..127,可通过 -XX:AutoBoxCacheMax 扩大)。缓存范围内返回同一个对象,范围外 new 一个新对象。
| 表达式 | 编译后 | 结果 |
|---|---|---|
Integer i = 127 |
Integer.valueOf(127) → 缓存对象 |
同一对象 → == true |
Integer i = 128 |
Integer.valueOf(128) → 新对象 |
不同对象 → == false |
new Integer(127) |
强制新建(已废弃,见下) | 不同对象 → == false |
new Integer(...)在 JDK 9 起标记废弃、后续版本标记移除(实测编译时有 warning)。生产代码不要用,让编译器走valueOf。
3. 四种比较,一张表说清
| 比较 | 比的是什么 | 建议 |
|---|---|---|
int == int |
数值 | ✅ |
Integer == Integer |
引用(缓存范围内可能"碰巧"相等) | ❌ 用 equals |
Integer == int |
拆箱后比数值 | ⚠️ 有 NPE 风险(Integer 为 null 时) |
Integer.equals(Integer) |
数值 | ✅ 推荐 |
实测补充:
new Integer(127)==127: true ← 右侧拆箱,比数值
new==new(127): false equals: true
注意 ==127 那种写法:右侧是 int,左侧 Integer 会自动拆箱——如果左侧是 null,直接 NullPointerException。这是 == 最危险的用法。
4. 值传递(E-S04-004)
Java 只有值传递:基本类型传值,对象传"引用的值"(引用的副本)。
void modify(int x) { x = 99; } // 不影响调用方
void modify(int[] a) { a[0] = 99; } // 影响(改的是同一个数组对象)
void reassign(int[] a) { a = new int[]{9}; } // 不影响(改的是副本引用)
| 操作 | 是否影响调用方 |
|---|---|
| 改基本类型形参 | ❌ |
| 改对象内部状态 | ✅ |
| 让形参指向新对象 | ❌ |
判据:"我改的是对象,还是引用本身?"
5. 字符串:常量池与 ==(预告 B08)
实测:
s1==s2: true // 字面量 → 常量池同一对象
s1==s3: false // new String → 堆上新对象
s1.equals(s3): true
常量折叠 s4==s1: true // "a"+"b"+"c" 编译期折叠
结论:字符串比较一律用 equals;== 只在你明确想比较"是否同一个对象"时用(几乎从不需要)。
6. 五个误区
| 误区 | 真相 |
|---|---|
"Integer == Integer 比较数值" |
比较引用(缓存范围内可能碰巧相等) |
| "127 与 128 是玄学" | 是 valueOf 缓存 −128..127 |
"可以用 new Integer()" |
已废弃/标记移除 |
| "Java 有引用传递" | 只有值传递(对象传引用的副本) |
"== null 与 equals(null) 等价" |
equals(null) 返回 false;== null 判断是否空引用 |
7. 自检
- 为什么
Integer a=127,b=127时a==b,而 128 时不等? Integer x = null; if (x == 1)会发生什么?modify(int[] a)与reassign(int[] a)的差别?new String("abc") == "abc"为什么 false?- 什么时候可以安全用
==比较对象?
8. 下一篇
S04-B03 · 流程控制与运算符
类型讲完,下一篇过一遍控制流——以及 Java 里几个容易踩的运算符细节(++、短路、位运算)。
本篇属于系列《S04 · Java 语言核心》。旧文来源:A-1698/1704/1762/1692/1760/1780/811;扩展点 E-S04-003/004。所有输出为 OpenJDK 21 实测。