java版本1.6.0_26
从书中进行SCJP考试准备:
为了节省内存,以下两个实例[来自-128和127的Short和Integer,以及其他一些但对问题无关紧要的]包装器对象(通过boixng创建)将始终为= =当它们的原始值相同时。
我做了什么:
如果我们将比较两个-128到127之间的整数:
1. Integer i1 = 10;
2. Integer i2 = 10;
3. System.out.println(i1 == i2); // true
但为什么同样给我们“假”或可能是不一样的东西:
4. Integer i3 = new Integer(10);
5. Integer i4 = new Integer(10);
6. System.out.println(i3 == i4); // false
我的问题:
1)在第一行代码中我们进行隐式装箱吗?
2)为什么第3行和第6行代码会给我们不同的结果?
答案 0 :(得分:7)
我们在第一行代码中进行隐式装箱吗?
Yes
2)为什么第3行和第6行代码会给我们不同的结果?
Integer.valueOf(int)
将所有值从-128汇集到127.
原因是经常使用小的Integer值,每次我们需要一个对象时,为所有这些值创建一个新对象是没有意义的。因此,它们被创建为“interned”对象,并且对这些整数值的所有引用将指向相同的内存地址。
来自Integer.java的代码片段:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
相反,当你调用new Integer(10);
时,它正在创建一个全新的对象,因此具有相同整数值的两个不同对象将指向不同的内存地址
答案 1 :(得分:2)
1) Does on the 1st line of code we make implicit boxing?
是。它被称为Auto-Boxing
2) Why the 3rd and 6th lines of code give us different results?
==实际检查两个变量是否具有完全相同的值。请注意,原始变量包含您看到的内容,但引用变量包含它所拥有的对象的地址。
当==用于将基元与包装器进行比较时,包装器将被解包并且比较将是原始的,因此它将是真实的,因为它是原始比较而不是对象比较。这就是为什么
System.out.println(i1 == i2);
将是真的。
但是在第6行。
System.out.println(i3 == i4);
您正在比较两个对象,除非对象具有相同的引用,否则它将不是真的。如果你使用.equals方法,你就可以成真。尝试
System.out.println(i3.equals(i4));
答案 2 :(得分:1)
在第一个示例中,编译器使用装箱来分配变量。在这种情况下,i1 / i2是常量(有点像静态最终对象)。
在第二个示例中,您创建了两个Integer实例,因此它们永远不会相同。
答案 3 :(得分:0)
6行显示为false,因为它正在比较引用i3
和i4
是否指向同一个对象!在这种情况下,它不是。因此false
。
如果涉及包装器和原语,则会出现Autoboxing和UnBoxing。这里i3
和i4
都是包装对象,因此它将被视为任何其他POJO
仅当包含包装器对象和原语时才会发生AutoBoxing,
例如
int primitive = 10;
Integer wrapper = new Integer(10);
System.out.println(primitive == wrapper); //true
在上面的True
比较中打印==
,将原语的值与包装器的状态进行比较。