在比较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 }