为什么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 }