Java的平等运算符是可交换的吗?

时间:2014-02-08 05:31:54

标签: java syntactic-sugar autoboxing

考虑以下Java代码:

Integer foo = bar();
if(foo == 5) ...;
if(5 == foo) ...;

这些比较是否相等 - 尤其是foo null的可能性?它们是扩展为foo.getValue() == 55 == foo.getValue(),还是更类似于foo.equals(new Integer(5))new Integer(5).equals(foo),还是其他内容?可能是其中一个或两个或两个都没有投入NPE?

3 个答案:

答案 0 :(得分:1)

来自JLS

  

15.21.1。数值等式算子==和!=

     

如果等于运算符的操作数都是数字类型,或者   一个是数字类型,另一个是可转换的(§5.1.8)   数字类型,对操作数执行二进制数字提升   (§5.6.2)。

5.1.8的相关规则是:

  

如果r是Integer类型的引用,则取消装箱转换会转换   r进入r.intValue()

5.6.2说:

  

5.6.2。二进制数字促销

     

当运算符将二进制数字提升应用于一对时   操作数,每个操作数必须表示可转换为a的值   数字类型,以下规则适用:

     

如果任何操作数属于引用类型,则将其取消装箱   转换(第5.1.8节)。

这意味着if(foo == 5) ...;if(foo.intValue() == 5) ...;相同,if(5 == foo)表示if (5 == foo.intValue())。 如果foo等于null,则无论如何都会获得NPE。

答案 1 :(得分:1)

== 对称;也就是说,对于任何值xy(x == y) == (y == x)。这是JLS §15.21.1为数字提供的保证,§15.21.3为参考类型(或所有非原始值)提供的保证。

它也可以被视为传递,因为如果存在三个值x, y, z,则x == y && y == z,然后x == z。这再次由相同的JLS规范提供 - 仅重复以缓解公共变量y的问题。

真正的问题来自于自动装箱;当您转到取消装箱null,然后by the JLS时,您将获得NullPointerException - 独立于您接下来将要执行的比较操作。

有效:

  • 比较的一侧有一个盒装基元类型,另一侧有基元。尚未考虑其中任何一个的价值。

  • 鉴于原始will force numerical comparison的值是由于它是一个盒装基元,Java将尝试取消装箱的值。

  • 您无法取消装箱null,因此NullPointerException

这是({3}}步入的地方 - 通过它的契约,如果它们确实是同一个东西,那么两个非空实例必须彼此相等。如果这些值中的任何一个(但不是两个)都是null,则它们不是相同的实例。

我说“有点”,因为在Object#equals上实际上并没有强制执行所谓的合同;你可以(通过一些努力)编写一个非对称的equals()方法,虽然有人会想知道你为什么要这样做。

答案 2 :(得分:0)

1)1和2之间没有区别

2)编译器将foo == 5转换为foo.intValue() == 5(发件箱)

3)如果foonull NPE在运行时被抛出