java上的行为不一致==

考虑以下代码:

class test { public static void main(String[] args) { test inst_test = new test(); int i1 = 2000; int i2 = 2000; int i3 = 2; int i4 = 2; Integer Ithree = new Integer(2); // 1 Integer Ifour = new Integer(2); // 2 System.out.println( Ithree == Ifour ); inst_test.method( i3 , i4 ); inst_test.method( i1 , i2 ); } public void method( Integer i , Integer eye ) { System.out.println(i == eye ); } } 

它打印:

 false true false 

我理解第一个false ,==运算符只检查两个引用是否在同一个对象上工作,在这种情况下不是。

以下的false都让我摸不着头脑。 为什么Java会认为i3i4相同但i1i2不同? 两者都被包装到Integer,不应该评估为false? 这种不一致是否有实际原因?

将基元自动装箱到对象中(在对method的调用中使用的method使用小值的缓存。来自Java语言规范部分5.1.7 :

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

紧随其后的规范的讨论部分也很有趣。 值得注意的是,JVM可以根据需要缓存更多值 – 您无法确定执行的结果:

 Integer i1 = 129; Integer i2 = 129; boolean b = (i1 == i2); 

自动装箱时,缓存介于-128和127之间的整数,并返回相同的包装器对象。 与\ u0000和\ u007F之间的布尔值和char值相同

这是大多数时候你会得到的,但它取决于JVM的实现。

这是因为拳击使得整数低于某个值(128,我认为)指的是一些预构造的对象,而更高的值指向新对象。

Autoboxing使用Integer.valueOf(i)而不是新的Integer(i)来构造Integer类的对象。

正如其他人所说,valueOf()使用缓存,主要是为了提高空间效率。

不要在引用类型上使用==,这几乎总是一个错误。

Integer类包含一些常用实例的缓存。 值的范围通常在JVM到JVM之间变化(有时也是可配置的)但通常相关代码类似于:

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

(来自sun JDK 1.6的代码)

这就像字符串实习一样,因为它既可以节省内存,又可以使用引用允许测试相等(例如==代替等号

我猜想包装会尝试最小化整数对象的数量,并且只创建一个表示2太多的内存对象。

只记得永远不要在对象上使用==你永远不知道会发生什么。

Autoboxing使用一些缓存机制。 通常你不应该依赖== ,总是使用equals来检查相等性。