为什么在比较 Java 中的 Integer 包装时,128 = = 128为假,而127 = = 127为真?

class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}

产出:

false

class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}

产出:

true

注意: -128和127之间的数字为真。

58285 次浏览

自动装箱缓存-128到127。这在JLS(5.1.7)中指定。

正在装箱的

如果值 P是TRUE、FALSE、一个字节、\u0000到\u007f范围内的一个字符或者一个介于-128和 127,则令R1和R2是任意两个装箱转换的结果 P的。通常情况下,R1==R2。

处理对象时要记住的一个简单规则是-如果要检查两个对象是否“相等”,则使用.equals;如果要查看它们是否指向同一实例,则使用==

当您在Java中编译一个数字文本并将其赋给一个整数(大写I)时,编译器会发出:

Integer b2 =Integer.valueOf(127)

使用自动装箱时也会生成这行代码。

valueOf被实现为使得某些数字是“ 0 ”。池";,并且对于小于128的值,它返回相同的实例。

来自Java 1.6源代码,第621行:

public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}

high的值可以配置为其他值,并具有系统属性。

-djava.Lang.integer.IntegerCache.high=999

如果使用该系统属性运行程序,它将输出true!

显而易见的结论是:永远不要依赖两个相同的参考文献,总是将它们与.equals()方法进行比较。

因此,对于B2、B3的所有逻辑相等值,__abc0将输出true.

注意,Integer高速缓存不是出于性能原因而存在,而是为了符合JLS,第5.1.7节;必须为值-128到127(包括这两个值)指定对象标识。

整数#valueOf(int)也记录了这种行为:

通过缓存频繁请求的值,此方法可能会产生明显更好的空间和时间性能。此方法将始终缓存-128到127(含)范围内的值,并可能缓存此范围之外的其他值。

使用基元数据类型int在两种情况下都会产生true,即预期的输出。

但是,由于您使用的是整数对象,因此==运算符具有不同的含义。

在对象的上下文中,==检查变量是否引用相同的对象引用。

要比较对象的值,应该使用equals()方法 例如:

 b2.equals(b1)

它将指示B2是否小于B1、大于或等于(有关详细信息,请查看API)

我写了下面的内容,因为这个问题不仅仅是针对整数的。我的结论是,如果你不正确地使用API,你通常会看到不正确的行为。正确使用它,您应该会看到正确的行为:

public static void main (String[] args) {
Byte b1=127;
Byte b2=127;


Short s1=127; //incorrect should use Byte
Short s2=127; //incorrect should use Byte
Short s3=128;
Short s4=128;


Integer i1=127; //incorrect should use Byte
Integer i2=127; //incorrect should use Byte
Integer i3=128;
Integer i4=128;


Integer i5=32767; //incorrect should use Short
Integer i6=32767; //incorrect should use Short


Long l1=127L;           //incorrect should use Byte
Long l2=127L;           //incorrect should use Byte
Long l3=13267L;         //incorrect should use Short
Long l4=32767L;         //incorrect should use Short
Long l5=2147483647L;    //incorrect should use Integer
Long l6=2147483647L;    //incorrect should use Integer
Long l7=2147483648L;
Long l8=2147483648L;


System.out.print(b1==b2); //true  (incorrect) Used API correctly
System.out.print(s1==s2); //true  (incorrect) Used API incorrectly
System.out.print(i1==i2); //true  (incorrect) Used API incorrectly
System.out.print(l1==l2); //true  (incorrect) Used API incorrectly


System.out.print(s3==s4); //false (correct) Used API correctly
System.out.print(i3==i4); //false (correct) Used API correctly
System.out.print(i5==i6); //false (correct) Used API correctly
System.out.print(l3==l4); //false (correct) Used API correctly
System.out.print(l7==l8); //false (correct) Used API correctly
System.out.print(l5==l6); //false (correct) Used API incorrectly


}

看一下Integer.Java,如果值在-128和127之间,它将使用缓存池,因此(Integer) 1 == (Integer) 1(Integer) 222 != (Integer) 222

 /**
* Returns an {@code Integer} instance representing the specified
* {@code int} value.  If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param  i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since  1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

这与Java中的内存优化有关。

为了节省内存,Java “重用”所有包装器对象,这些对象的值 属于以下范围:

所有布尔值(true和false)

所有字节值

从\u0000到\u007f的所有字符值(即十进制的0到127)

从-128到127的所有短整型值。

其他答案描述了为什么可以观察到观察到的效果,但这对程序员来说并不重要(当然,这很有趣,但在编写实际代码时,您应该忘记这一点)。

要比较Integer对象是否相等,请使用equals方法。

不要试图使用标识运算符(==)来比较Integer对象是否相等。

可能会发生一些相等的值是相同的对象,但这不是通常应该依赖的东西。

如果该值介于-128和127之间,则将使用缓存池,只有在自动装箱时才是这样。 所以你会有以下:

    public static void main(String[] args) {
Integer a  = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b);         // false. == compare two instances, they are difference
System.out.println(a.equals(b));    // true. equals compares the value


Integer a2 = 100;
Integer b2 = 100;
System.out.println(a2 == b2);       // true. auto-boxing uses cached pool between -128/127
System.out.println(a2.equals(b2));  // true. equals compares the value


Integer a3 = 129;
Integer b3 = 129;
System.out.println(a3 == b3);       // false. not using cached pool
System.out.println(a3.equals(b3));  // true. equals compares the value
}
}