[英]Inconsistent behavior on java's ==
考虑以下代码:
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
,==运算符仅检查两个引用是否在同一个对象上工作,在这种情况下不是。
以下true
与false
让我挠头。 Java为什么会认为i3
和i4
相等但i1
和i2
不同? 两者都包装在Integer中,难道都不都应该为假? 是否存在这种不一致的实际原因?
将原语自动装箱到对象中(在对method
的调用中使用的是使用小的值的缓存。请参见Java语言规范第5.1.7节 :
如果要装箱的值p为true,false,一个字节,介于\\ u0000到\\ u007f之间的char或-128和127之间的int或short数字,则令r1和r2为任何两次装箱转换的结果的p。 r1 == r2总是这样。
紧随其后的规范讨论部分也很有趣。 值得注意的是,JVM可以根据需要缓存更多的值-您不能确定这样做的结果:
Integer i1 = 129;
Integer i2 = 129;
boolean b = (i1 == i2);
自动装箱时,将缓存-128和127之间的整数,并返回相同的包装对象。 \\ u0000和\\ u007F之间的布尔值和char值相同
这是您大部分时间所获得的,但是它取决于JVM的实现。
这是因为装箱会使低于某个值(我认为是128)的整数引用某些预先构造的对象,而将更高的值引用到新对象。
自动装箱使用Integer.valueOf(i)而非新的Integer(i)来构造Integer类的对象。
正如其他人所说,valueOf()使用缓存,主要是为了提高空间效率。
不要在引用类型上使用==,这几乎总是一个错误。
我猜想包装会尽量减少Integer对象的数量,并只创建一个代表2个对象的对象,这也可以节省内存。
只要记住永远不要在对象上使用==,就永远不知道会发生什么。
整数类包含一些常用实例的缓存。 值的范围通常因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的代码)
这就像字符串实习,因为它既节省了内存,又允许使用引用进行测试相等(例如==代替equals )
自动装箱使用某些缓存机制。 通常,您永远不要依赖==
,始终使用equals
来检查相等性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.