在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中工作?是否,或者不是,检查对象'比较它们时的内容?
谢谢!
答案 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
值,该值是-128
到127
int池的一部分。因此,在对象级别上,他们确实相同,而==
就是这样。
答案 2 :(得分:1)
当你自动提交int时,你在内部调用Integer.valueOf(int)
,根据文档可能会返回缓存的值。因此,您完全了解您的参考平等。
更一般地说,除非您明确构造它们,否则不应假设两个引用是不同的。而对于记录,字符串实习也可以在运行时通过String.intern()
方法获得。