比较装箱的Long值127和128


110

我想使用条件比较两个Long对象的值if。当这些值小于128时if条件将正常工作,但是当这些值大于或等于128时,比较将失败。

例:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

上面代码的比较正常进行,但是下面代码失败:

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

为什么将Long变量的值大于127进行比较存在问题?如果将变量数据类型更改为长原语,则比较适用于所有情况。

Answers:


212

TL; DR

Java将盒装的Integer实例从缓存-128127。由于您==用于比较对象引用而不是,因此只有缓存的对象会匹配。使用未long装箱的原始值或用于.equals()比较Long对象。

长(双关语意)版本

为什么将Long变量的值大于127进行比较存在问题?如果上述变量的数据类型是原始(长整数),则代码对所有值有效。

Java缓存范围从-128到127的Integer对象实例。说:

  • 如果将值127cached)设置为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()方法始终是一个好主意。

参考链接:


15

Java将原始值从-128缓存到127。当我们比较两个Long对象时,java在内部内部将其强制转换为原始值并进行比较。但是127以上的Long对象将不会获得等级等级。Java通过.valueOf()方法缓存输出。

此缓存适用于从-128到127的Byte,Short,Long。对于Integer缓存,从-128到java.lang.Integer.IntegerCache.high或127(以较大者为准)有效。(我们可以将顶级值设置为最大Integer值应该通过使用java.lang.Integer.IntegerCache.high进行缓存)。

 For example:
    If we set java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

浮点和双精度对象永远不会被缓存。

角色将从0到127缓存

您正在比较两个对象。因此==运算符将检查对象引用是否相等。有以下几种方法可以做到这一点。

1)类型将两个对象都转换为原始值并进行比较

    (long)val3 == (long)val4

2)读取对象的值并进行比较

    val3.longValue() == val4.longValue()

3)在对象比较中使用equals()方法。

    val3.equals(val4);  

14

num1并且num2是长物体。您应该使用equals()它们进行比较。 ==有时由于JVM框原语的方式而使比较可行,但不要依赖它。

if (num1.equals(num1))
{
 //code
}

1
这(更好),或比较的返回值.longValue()
Giulio Franco

4

将Java中的非原始元素(也称为对象)与==比较它们的引用而不是它们的值。Long是一堂课,因此Long值是对象。

问题是Java开发人员希望人们Long像以前那样使用它们long来提供兼容性,这导致了自动装箱的概念,该概念本质上就是功能,即根据需要longLong-values 更改为-Objects,反之亦然。但是,由于没有完全指定自动装箱的行为,因此并非始终可以完全预测到。

因此,为了安全起见并获得可预测的结果,总是使用这种方法.equals()来比较对象,并且在这种情况下不依赖自动装箱:

Long num1 = 127, num2 = 127;
if(num1.equals(num2)) { iWillBeExecutedAlways(); }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.