原始包装比较

时间:2012-12-27 06:17:45

标签: java scjp

  

可能重复:
  Using == operator in Java to compare wrapper objects

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行代码会给我们不同的结果?

4 个答案:

答案 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,因为它正在比较引用i3i4是否指向同一个对象!在这种情况下,它不是。因此false

如果涉及包装器和原语,则会出现Autoboxing和UnBoxing。这里i3i4都是包装对象,因此它将被视为任何其他POJO

仅当包含包装器对象和原语时才会发生AutoBoxing,

例如

int primitive = 10;
Integer wrapper = new Integer(10);
System.out.println(primitive == wrapper); //true

在上面的True比较中打印==,将原语的值与包装器的状态进行比较。