比较加框的长值127和128

我想使用if条件比较两个Long对象值。 当这些值小于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的值存在问题? 如果变量数据类型更改为长基元 ,则比较适用于所有情况。

TL; DR

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

长版

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

Java缓存范围为-128到127的整数对象实例 。 那说:

  • 如果设置为N Long变量值127缓存 ),则所有引用都将指向相同的对象实例。 (N个变量,1个实例)
  • 如果设置为N Long变量值128未缓存 ),则每个引用都会指向一个对象实例。 (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原始值)与==运算符进行比较。 如果不是这种Cache机制,那么这些比较总是会失败,所以这里真正的问题是将盒装值与==运算符进行比较。

将这些变量更改为原始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 ,在处理Object比较时坚持使用.equals()方法总是一个好主意。

免责声明:如果这些值中的任何一个为空(即使转换为long将抛出exception),大多数比较都将失败,因此需要额外的检查来适应这些情况。

参考链接:

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

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

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

这个缓存适用于-128到127的字节,短,长。对于整数缓存工作从-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获得缓存

您正在比较两个对象。 so == operator将检查对象引用的相等性。 有以下方法可以做到这一点。

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

  (long)val3 == (long)val4 

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

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

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

  val3.equals(val4); 

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

问题是Java开发人员希望人们像long使用Long那样使用Long来提供兼容性,从而导致自动装箱的概念,其本质上就是这个特性, long将根据需要更改为Long -Objects,反之亦然。 然而,自动装箱的行为并不是完全可预测的,因为它没有完全指定。

因此,为了安全并具有可预测的结果,请始终使用.equals()来比较对象,并且在这种情况下不依赖于自动装箱:

 Long num1 = 127, num2 = 127; if(num1.equals(num2)) { iWillBeExecutedAlways(); }