比较盒装长整型值 127 和 128

2022-08-31 09:24:01

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

例:

Long num1 = 127;
Long num2 = 127;

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

上述代码的比较工作正常,但在以下代码中失败:

Long num1 = 128;
Long num2 = 128;

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

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


答案 1

TL;DR

Java 将盒装整数实例从 高速缓存到 。由于 您 使用的是比较对象引用而不是,因此只有缓存的对象才会匹配。可以使用未装箱的基元值,也可以使用 来比较对象。-128127==long.equals()Long

长(双关语)版本

为什么将多头变量与大于 127 的值进行比较时存在问题?如果上述变量的数据类型是基元(长整型),则代码适用于所有值。

Java 缓存范围为 -128 到 127 的 Integer 对象实例。可是:

  • 如果将值(缓存)设置为 N Long 变量,则所有引用都将指向同一对象实例。(N 个变量,1 个实例)127
  • 如果将值设置为 N Long 变量(未缓存),则每个引用都将有一个对象实例。(N 个变量,N 个实例)128

这就是为什么:

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

发生这种情况仅仅是因为您正在将两个对象引用(而不是基元值)与运算符进行比较。如果不是这种缓存机制,这些比较将始终失败,因此此处的真正问题是将盒装值与运算符进行比较。Longlong====

将这些变量更改为基元类型将防止这种情况发生,但是如果您需要使用对象保留代码,则可以使用以下方法安全地进行这些比较:longLong

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()方法总是一个好主意。

参考链接:


答案 2

num1并且是长对象。您应该 使用 来比较它们。 比较有时可能会起作用,因为JVM盒子原语的方式,但不要依赖它。num2equals()==

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

推荐