考虑以下代码:
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,不应该两者评估为false?这种不一致是否有实际原因?
答案 0 :(得分:15)
将基元自动装箱到对象中(在调用method
时使用)会使用较小值的缓存。来自Java Language Specification section 5.1.7:
如果装箱的值p为真, false,一个字节,范围内的char \ u0000到\ u007f,或者是int或short 在-128和127之间的数字,然后让 r1和r2是任意两个的结果 p的拳击转换它始终是 r1 == r2。
的情况
紧随其后的规范的讨论部分也很有趣。值得注意的是,JVM可以根据需要缓存更多值 - 您无法确定执行的结果:
Integer i1 = 129;
Integer i2 = 129;
boolean b = (i1 == i2);
答案 1 :(得分:7)
自动装箱时,缓存-128到127之间的整数,并返回相同的包装器对象。与\ u0000和\ u007F
之间的布尔值和char值相同这是大多数时候你得到的,但它取决于JVM的实现。
答案 2 :(得分:2)
这是因为拳击使得整数低于某个值(128,我认为)是指一些预构造的对象,而更高的值是指新对象。
答案 3 :(得分:1)
Autoboxing使用 Integer.valueOf(i),而不是新的Integer(i)来构造Integer类的对象。
正如其他人所说,valueOf()使用缓存,主要是为了提高空间效率。
不要在引用类型上使用==,这几乎总是一个错误。
答案 4 :(得分:0)
我猜想包装会尝试最小化整数对象的数量,并且只创建一个表示2太多的内存对象。
请记住永远不要在对象上使用==你永远不知道会发生什么。
答案 5 :(得分:0)
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的代码)
这就像字符串实习一样,因为它既可以节省内存,又可以使用引用允许测试相等(例如 == 代替等于)
答案 6 :(得分:0)
Autoboxing使用一些缓存机制。通常,您不应该依赖==
,始终使用equals
来检查相等性。