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会认为i3
和i4
相同但i1
和i2
不同? 两者都被包装到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
来检查相等性。