为什么通过引用(==)比较整数有效?

时间:2015-03-08 11:02:32

标签: java comparison operators equality

在Herbert Schildt" Java:The Complete Reference,第9版"中,有一个例子让我感到困惑。我无法理解的关键点可归纳为以下代码:

class Test {
    public static void main (String args[]) {               
        Integer i1 = 6;
        Integer i2 = 6;

        Integer i3 = 6;
        Integer i4 = (args.length + 1) * 6;

        if (i1 == i2) System.out.println("WTF");
        if (i3 == i4) System.out.println("Super WTF!!!");
    }
}

令我惊讶的是,使用JDK 8 update 40编译和执行此类代码的结果如下:

WTF
Super WTF!!!

我所见过的所有Java书籍,手册和其他信息资源都表明,当用于比较对象时,相等运算符(==)只是匹配它们的引用值。因此,如果两个对象变量引用不同的实例,则==运算符返回false,即使这些对象的内部内容相同。这与上面例子所表达的行为截然不同。

在检查SO以查找类似问题时,我找到somewhat related one,其中使用String来比较==个对象。在那里,提到了一个名为interning的Java的有趣特性。显然,所有字符串文字和编译时字符串常量都是" cached"通过JVM,例如,使用相同的字符串文字初始化的多个String引用实际上指向同一个对象。

但在这里我们处理数值和Integer个对象。此外,其中一个变量i4使用提供给程序的许多命令行参数进行初始化,这绝对是一个运行时信息。但是,==仍然认为它等于i3

所以,鉴于以上所有,等于运算符应该如何在Java中工作?是否,或者不是,检查对象'比较它们时的内容?

谢谢!

3 个答案:

答案 0 :(得分:4)

Integer#valueOf(int)的Javadoc所提及的那样缓存

Integer个对象:

  

此方法将始终缓存-128到127(包括端点)范围内的值,并可以缓存此范围之外的其他值。

语句Integer i4 = (args.length + 1) * 6;调用Integer#valueOf(int),返回缓存的实例。另一方面,如果使用Integer i4 = new Integer((args.length + 1) * 6);,引用相等性将返回false。

答案 1 :(得分:2)

我认为该示例向我们展示了java int pool的工作原理。因此,在i4情况下,如果在运行时没有提供参数,则结果为6。现在,int池启动并使用i1值,该值是-128127 int池的一部分。因此,在对象级别上,他们确实相同,而==就是这样。

答案 2 :(得分:1)

当你自动提交int时,你在内部调用Integer.valueOf(int),根据文档可能会返回缓存的值。因此,您完全了解您的参考平等。

更一般地说,除非您明确构造它们,否则不应假设两个引用是不同的。而对于记录,字符串实习也可以在运行时通过String.intern()方法获得。