比较装箱的长值127和128

时间:2013-12-12 10:59:35

标签: java comparison autoboxing

我想使用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
}

为什么在变量与大于127 的值进行比较时会出现问题?如果变量数据类型更改为 long primitives ,则比较适用于所有情况。

4 个答案:

答案 0 :(得分:191)

<强> TL; DR

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

长(双关语版)

  

为什么将Long变量与大于127的值进行比较时出现问题?如果上面变量的数据类型是原始的(长),则代码适用于所有值。

<强> Java caches Integer objects instances from the range -128 to 127 即可。那说:

  • 如果设置为N Long变量值127 cached ),则所有引用都将指向相同的对象实例。 (N个变量,1个实例)
  • 如果设置为N Long变量值128 not cached ),则每个引用都会指向一个对象实例。 (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()方法总是一个好主意。

参考链接:

答案 1 :(得分:14)

num1num2是Long对象。您应该使用equals()来比较它们。 ==比较有时可能会起作用,因为JVM框原语的方式,但不依赖它。

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

答案 2 :(得分:13)

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

此缓存适用于-128到127的Byte,Short,Long。 对于整数缓存工作从-128到java.lang.Integer.IntegerCache.high或127,以较大者为准。(我们可以通过使用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".

Float和Double对象永远不会被缓存。

字符将从0到127缓存

您正在比较两个对象。所以 == 运算符将检查对象引用的相等性。有以下方法可以做到。

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

    (long)val3 == (long)val4

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

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

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

    val3.equals(val4);  

答案 3 :(得分:4)

将Java中的非基元(又称对象)与==进行比较,比较它们的引用而不是它们的值。 Long是一个类,因此Long值是对象。

问题是Java开发人员希望人们使用Long,就像他们使用long来提供兼容性一样,这导致了自动装箱的概念,这基本上就是{{1} } -values将根据需要更改为long - 对象,反之亦然。然而,自动装箱的行为并不是完全可预测的,因为它没有完全指定。

因此,为了安全起见并获得可预测的结果,请始终使用Long来比较对象,并且在这种情况下不依赖于自动装箱:

.equals()