在比较Java中的整数包装器时,为什么128 == 128 false但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之间的数字为真。
当您在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); }
可以使用system属性将high
的值配置为其他值。
-Djava.lang.Integer.IntegerCache.high = 999
如果您使用该系统属性运行程序,它将输出true!
明显的结论是:永远不要依赖两个相同的引用,总是将它们与.equals()
方法进行比较。
因此b2.equals(b3)
将对所有逻辑上相等的b2,b3值打印为true。
请注意,出于性能原因,Integer缓存不存在,而是符合JLS,第5.1.7节 ; 必须为值-128到127(包括端点)给出对象标识。
整数#valueOf(int)也记录了这种行为:
通过缓存频繁请求的值,此方法可能会显着提高空间和时间性能。 此方法将始终缓存-128到127(包括端点)范围内的值,并可以缓存此范围之外的其他值。
自动装箱缓存-128到127.这在JLS( 5.1.7 )中指定。
如果 被装箱 的值 p 为true,false,一个字节,范围为\ u0000到\ u007f的字符,或者介于-128和127之间的int或短号,则让r1和r2为任意两次装箱转换的结果of p。 始终是r1 == r2的情况。
处理对象时要记住的一个简单规则是 – 如果要检查两个对象是否“相等”,请使用.equals,当您想要查看它们是否指向同一个实例时,请使用==。
使用原始数据类型int,在两种情况下都会产生预期的输出。
但是,由于您使用的是Integer对象,因此==运算符具有不同的含义。
在对象的上下文中,==检查变量是否引用相同的对象引用。
要比较对象的值,您应该使用equals()方法Eg
b2.equals(b1)
这将指示b2是否小于b1,大于或等于(查看API了解详情)
它与Java相关的内存优化。
为了节省内存,Java’重用’其值落在以下范围内的所有包装器对象:
所有布尔值(true和false)
所有字节值
从\ u0000到\ u007f的所有字符值(即十进制中的0到127)
所有短整数和整数值从-128到127。
注意:
-
如果使用new Boolean(value)创建Boolean; 你将永远得到新的对象
-
如果你用新的String(值)创建String; 你将永远得到新的对象
-
如果用新的Integer(value)创建Integer; 你将永远得到新的对象
等等
看一下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); }
我写了以下内容,因为这个问题不仅仅针对Integer。 我的结论是,如果你错误地使用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 }