为什么128 == 128返回false但是127 == 127在转换为Integer包装器时返回true?

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之间的数字是正确的。

当你在Java中编译一个数字文字并将其分配给一个Integer(大写I )时,编译器发出:

 Integer b2 =Integer.valueOf(127) 

这行代码也是在使用自动装箱时生成的。

valueOf是这样实现的:某些数字是“合并的”,并且它返回的值小于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的值configuration为另一个值。

-Djava.lang.Integer.IntegerCache.high = 999

如果您使用该系统属性运行您的程序,它将输出真实!

明显的结论是:永远不要依赖于两个引用是相同的,总是将它们与.equals()方法进行比较。

所以b2.equals(b3)将打印所有在逻辑上等于b2,b3的值。

请注意,Integercaching不是出于性能原因,而是为了符合JLS第5.1.7节 ; 对象身份必须给予值-128到127(含)。

整数#valueOf(int)也logging了这个行为:

这种方法可能通过caching频繁请求的值来产生显着更好的空间和时间性能。 此方法将始终caching范围-128至127(含)范围内的值,并可caching此范围之外的其他值。

自动装箱caching-128至127.这在JLS( 5.1.7 )中有规定。

如果 p 的值为 真,false,一个字节,范围在\ u0000到\ u00f之间的一个字符,或者在-128到127之间的一个int或者short,然后让r1和r2是任意两个装箱转换的结果p。 r1 == r2总是如此。

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

使用原始数据typesints,在两种情况下都会产生预期的输出。

但是,由于您使用Integer对象,所以==运算符具有不同的含义。

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

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

  b2.equals(b1) 

这将指示b2是否小于b1,大于或等于(详情请查看API)

看看Integer.java,如果这个值在-128到127之间,它将使用caching池,所以(Integer) 1 == (Integer) 1 while (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的所有Short和Integer值。

注意:

  • 如果使用新的布尔(值)创build布尔值; 你将永远得到新的对象

  • 如果你用新的String(value)创buildString; 你将永远得到新的对象

  • 如果用新的Integer(value)创buildInteger; 你将永远得到新的对象

等等

我写了以下内容,因为这个问题不只是针对整数。 我的结论是,如果你不正确地使用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 }