Java 中 Long 比较的 “127 陷阱”
·
Java 中 Long 比较的 “127 陷阱”:为什么超过 127 后不能用 ==?
在 Java 开发中,Long 作为 long 的包装类,经常需要进行比较操作。然而开发者常会遇到一个奇怪现象:当 Long 对象值 ≤127 时,== 比较返回 true;当值 >127 时,== 却返回 false,必须使用 equals 方法才能正确比较。这究竟是怎么回事?让我们深入解析这个 “127 陷阱”。
一、现象观察:127 是分界线
通过以下代码可以直观看到这个现象:
public class LongCompareDemo {
public static void main(String[] args) {
Long a = 127L;
Long b = 127L;
System.out.println(a == b); // true
Long c = 128L;
Long d = 128L;
System.out.println(c == d); // false
System.out.println(c.equals(d)); // true
}
}
同样的比较操作,127 时 == 返回 true,128 时却返回 false。这不是 Java 的 bug,而是 Long 的缓存机制与 == 运算符特性共同作用的结果。
二、原理分析:自动装箱与缓存机制
1. == 运算符的行为特性
在 Java 中:
- 比较基本类型(如 long、int)时,== 比较值是否相等
- 比较引用类型(如 Long、String)时,== 比较对象内存地址是否相同
Long 是引用类型,因此 Long a == Long b 实际上是判断两个变量是否指向同一个对象。
2. 自动装箱与缓存实现
Long a = 127L 这样的赋值会触发自动装箱,底层调用的是 Long.valueOf(long)。查看源码(JDK 8):
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // 缓存范围
return LongCache.cache[(int)l + offset];
}
return new Long(l); // 超出范围创建新对象
}
缓存机制的关键点:
- 值在 -128~127 范围内时,返回缓存中的 Long 对象
- 超出该范围时,每次都会新建 Long 对象
这就是为什么 127 时 == 比较返回 true(指向同一缓存对象),而 128 时 == 比较返回 false(新建不同对象)。
三、正确做法:使用 equals 方法
Long 类重写了 equals 方法,会正确比较包装的 long 值:
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).value;
}
return false;
}
因此,比较 Long 对象的值时,应该始终使用 equals 方法。
四、开发注意事项
-
明确区分类型:
- long:基本类型,用 == 比较
- Long:包装类,用 equals 比较
-
警惕自动装箱:
- 方法参数为 Long 时,传入 long 值会触发自动装箱
- 例如 method(128L) 会产生新对象
-
其他包装类:
- Integer/Short/Byte:缓存范围 -128~127
- Character:缓存范围 0~127
- Double/Float:无缓存机制
五、总结要点
"127 陷阱"的根源:
- == 比较的是对象引用而非值
- Long 对 -128~127 范围内的值做了缓存
最佳实践:
- 比较包装类对象时,始终使用 equals 方法
- 理解 == 和 equals 的本质区别:前者比较对象身份,后者比较对象值
更多推荐


所有评论(0)