为什么等于运算符的Integer值直到128数?

为什么Integer “=”运算符不适用于128和Integer值之后? 有人可以解释这种情况吗?

这是我的Java环境:java版“1.6.0_37”

Java(TM)SE运行时环境(版本1.6.0_37-b06)

Java HotSpot(TM)64位服务器VM(内置20.12-b01,混合模式)

示例代码:

Integer a; Integer b; a = 129; b = 129; for (int i = 0; i < 200; i++) { a = i; b = i; if (a != b) { System.out.println("Value:"+ i + " - Different values"); } else { System.out.println("Value"+ i + " Same values"); } } 

控制台输出的某些部分:

 Value:124 - Same values Value:125 - Same values Value:126 - Same values Value:127 - Same values Value:128 - Different values Value:129 - Different values Value:130 - Different values Value:131 - Different values Value:132 - Different values 

谢谢!

查看Integer的源代码 。 您可以在那里看到值的缓存。

只有在使用Integer.valueOf(int)时才会发生缓存,而不是在使用new Integer(int) 。 您使用的自动装箱使用Integer.valueOf

根据JLS ,您可以始终指望对于介于-128和127之间的值,在自动装箱后获得相同的Integer对象,并且在某些实现中,即使对于更高的值,您也可能获得相同的对象。

实际上在Java 7中(我认为在较新版本的Java 6中),IntegerCache类的实现已经改变,上限不再是硬编码的,但可以通过属性“java.lang.Integer.IntegerCache”进行配置。高“,所以如果使用VM参数-Djava.lang.Integer.IntegerCache.high=1000运行程序,则所有值都会得到”相同值“。

但是JLS仍然保证它直到127:

理想情况下,装箱给定的原始值p将始终产生相同的参考。 实际上,使用现有的实现技术可能不可行。 上述规则是务实的妥协。 上面的最后一个条款要求将某些常见值装入无法区分的对象中。 实现可以懒惰或急切地缓存这些。

对于其他值,此公式不允许对程序员的盒装值的身份进行任何假设。 这将允许(但不要求)共享部分或全部这些引用。

这确保了在大多数常见情况下,行为将是期望的行为,而不会造成过度的性能损失,尤其是在小型设备上。 例如,较少内存限制的实现可以缓存所有字符和短路,以及-32K – + 32K范围内的整数和长整数。

Integerint的包装类。

Integer != Integer比较实际的对象引用,其中int != int将比较值。

如前所述,缓存了值-128到127,因此返回相同的对象。

如果超出该范围,将创建单独的对象,因此引用将不同。

要解决这个问题:

  • 使类型为int
  • 将类型转换为int
  • 使用.equals()

根据Java语言规范:

如果被装箱的值p为true,false,一个字节,范围为\ u0000到\ u007f的字符,或者介于-128和127之间的int或短号,则让r1和r2为任意两次装箱转换的结果of p。 始终是r1 == r2的情况。

JLS拳击转换

有关int缓存的更多信息,请参阅此文章

Integer对象具有内部缓存机制:

 private static class IntegerCache { static final int high; static final Integer cache[]; static { final int low = -128; // high value may be configured by property int h = 127; if (integerCacheHighPropValue != null) { // Use Long.decode here to avoid invoking methods that // require Integer's autoboxing cache to be initialized int i = Long.decode(integerCacheHighPropValue).intValue(); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - -low); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} } 

另见valueOf方法:

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

这就是为什么你应该使用valueOf而不是new Integer 。 Autoboxing使用此缓存。

另见这篇文章: https : //effective-java.com/2010/01/java-performance-tuning-with-maximizing-integer-valueofint/

使用==不是一个好主意,使用equals比较值。

使用.equals()而不是==

整数值仅缓存在-127和128之间的数字,因为它们最常用。

 if (a.equals(b)) { ... } 

根据您获取Integer实例的方式,它可能不适用于任何值:

 System.out.println(new Integer(1) == new Integer(1)); 

版画

 false 

这是因为应用于引用类型操作数的==运算符与这些操作数表示的值无关。

这是因为Integer类的实现逻辑。 它已准备好数字对象直到128.您可以查看http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Integer.java打开源例如-jdk(搜索cache [])。
基本上不应该使用==来比较对象,只有Enums有一个例外。