TL; DR
Java将盒装的Integer实例从缓存-128
到127
。由于您==
用于比较对象引用而不是值,因此只有缓存的对象会匹配。使用未long
装箱的原始值或用于.equals()
比较Long
对象。
长(双关语意)版本
为什么将Long变量的值大于127进行比较存在问题?如果上述变量的数据类型是原始(长整数),则代码对所有值有效。
Java缓存范围从-128到127的Integer对象实例。说:
- 如果将值
127
(cached)设置为N个Long变量,则所有引用将指向同一对象实例。(N个变量,1个实例)
- 如果将值
128
(不缓存)设置为N个Long变量,则每个引用都将指向一个对象实例。(N个变量,N个实例)
这就是为什么:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2);
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4);
输出此:
真
假
对于127L值,由于两个引用(val1和val2)都指向内存(已缓存)中的同一对象实例,因此它返回true
。
另一方面,对于128值,由于在内存中没有高速缓存的实例,因此将为盒装值的任何新分配创建一个新实例,从而导致两个不同的实例(由val3和val4指向)并返回false
在他们之间的比较。
发生这种情况的唯一原因是,您正在将两个Long
对象引用(而不是long
原始值)与==
运算符进行比较。如果不是这种缓存机制,那么这些比较将始终失败,因此,这里的真正问题是将装箱的值与==
运算符进行比较。
将这些变量更改为原始long
类型将防止这种情况的发生,但是如果您需要使用Long
对象保留代码,则可以使用以下方法安全地进行这些比较:
System.out.println(val3.equals(val4)); // true
System.out.println(val3.longValue() == val4.longValue()); // true
System.out.println((long)val3 == (long)val4); // true
(即使是强制转换,也必须进行正确的空检查)
IMO,在处理对象比较时始终坚持使用.equals()方法始终是一个好主意。
参考链接:
.longValue()
。