在Java中,新的Integer(i) == i是有保证的吗?

26

考虑以下代码片段:

    int i = 99999999;
    byte b = 99;
    short s = 9999;
    Integer ii = Integer.valueOf(9); // should be within cache

    System.out.println(new Integer(i) == i); // "true"
    System.out.println(new Integer(b) == b); // "true"
    System.out.println(new Integer(s) == s); // "true"
    System.out.println(new Integer(ii) == ii); // "false"

很明显为什么最后一行会始终打印"false": 我们使用了==引用标识比较,而new对象永远不会等于已存在的对象。

这个问题是关于前三行的:这些比较是否保证是在原始类型int上进行的,并且自动拆箱为Integer?是否有情况下会自动装箱成引用类型,从而执行引用标识比较?(然后全部都是false!)


你的问题中是否有错别字 - 所有4个比较都使用了==,这将返回false,因为你正在左侧创建一个新实例。 - mdma
好的,我明白了。很棒的问题! - mdma
2个回答

21

是的。JLS §5.6.2规定了二进制数值提升的规则。其中一部分内容如下:

当运算符将二进制数值提升应用于一对操作数时,每个操作数都必须表示可转换为数字类型的值,按照以下规则依次应用,使用扩展转换(§5.1.2)根据需要转换操作数:

如果任何一个操作数是引用类型,则执行拆箱转换(§5.1.8)。

二进制数值提升适用于多个数值运算符,包括“数值相等运算符==和!=”。

JLS §15.21.1(数值相等运算符==和!=)指定:

如果相等运算符的操作数都是数值类型,或者一个是数值类型而另一个可以转换为数值类型(§5.1.8),则在操作数上执行二进制数值提升(§5.6.2)。

相比之下,JLS §15.21.3(引用相等运算符==和!=)提供了:

如果等式运算符的操作数都是引用类型或空类型,则该操作是对象相等性。这符合装箱和拆箱的常见理解,即只在存在不匹配时才进行。

这似乎意味着new Integer(0) == new Integer(0)(结果为 false)应该等于 true,因为“任何一个操作数是引用类型时都会执行拆箱转换”。你能进一步澄清这个问题吗? - polygenelubricants
它适用于算术运算符,在new Integer(0)==new Integer(0)中,'=='是引用相等性运算符,而不是算术运算符。 - mdma
1
@polygene,我进一步解释了为什么你的评论示例使用对象相等性。 - Matthew Flaschen

9
我将首先解释“==”何时是引用相等,何时是数值相等。引用相等的条件比较简单,因此首先进行解释。

JLS 15.21.3 引用相等运算符 ==!=

如果等式运算符的操作数都是引用类型或null类型,则该操作为对象相等。

这解释了以下内容:

System.out.println(new Integer(0) == new Integer(0)); // "false"

两个操作数都是引用类型的Integer,因此==是引用相等比较,两个new对象永远不会==,所以输出false

要使==成为数字相等,至少有一个操作数必须是数字类型;如下所示:

JLS 15.21.1 数字等式运算符==!=

如果等式运算符的操作数都是数字类型,或者其中一个是数字类型且另一个可转换为数字类型,则对操作数执行二进制数值提升。如果操作数的提升类型是intlong,则执行整数等式测试;如果提升类型是floatdouble,则执行浮点等式测试。

请注意,二进制数值提升执行值集转换和取消装箱转换。

因此,请考虑以下内容:

System.out.println(new Integer(0) == 0); // "true"

这会打印true,因为:

  • 右操作数数字类型int
  • 左操作数可以转换为数字类型,通过拆箱到int
  • 因此==是一个数值相等的操作

概述

  • 如果==!=的两个操作数都是引用类型,那么它将始终是一个引用相等性操作。
    • 无论操作数是否可转换为数字类型都没有关系。
  • 如果至少有一个操作数是数字类型,则它将始终是一个数字相等性操作。
    • 如果需要,将在一个(最多!)操作数上执行自动解包装。

参考资料

相关问题


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接