是否保证Java中的新Integer(i)== i?

时间:2010-05-14 05:06:27

标签: java comparison autoboxing implicit-conversion

请考虑以下代码段:

    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对象将永远 ==为现有对象。

问题是关于前3行:那些 保证 与原始int进行比较,Integer自动拆箱?是否存在基元将被自动装箱的情况,并且执行参考标识比较? (这将是false!)

2 个答案:

答案 0 :(得分:20)

是。 JLS §5.6.2指定二进制数字促销的规则。部分:

  

当运算符应用二进制时   数字促销到一对   操作数,每个都必须表示一个   可转换为数字的值   类型,以下规则适用于   订单,使用加宽转换   (§5.1.2)将操作数转换为   必要的:

     

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

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

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

  

如果操作数相等   运算符都是数字类型,或   一个是数字类型,另一个是数字类型   可转换(第5.1.8节)为数字   类型,二进制数字促销是   在操作数上执行(第5.6.2节)。

相反,JLS §15.21.3(参考等式运算符==和!=)提供:

  

如果操作数相等   运算符都是参考   键入或null类型,然后是   操作是对象相等

这符合拳击和拆箱的常识,只有在不匹配时才会这样做。

答案 1 :(得分:7)

我将首先解释 ==是引用相等的时候,正好时它是数字相等。引用相等的条件更简单,因此首先解释它。

JLS 15.21.3 Reference Equality Operators == and !=

  

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

这解释了以下内容:

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

两个操作数都是Integer,它们是引用类型,这就是==是引用相等比较的原因,而两个new对象永远不会是== ,这就是它打印false的原因。

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

JLS 15.21.1 Numerical Equality Operators == and !=

  

如果等于运算符的操作数 的数值类型,或一个的数字类型,另一个可转换为数字类型,对操作数执行二进制数字提升。如果提升的操作数类型是intlong,则执行整数相等测试;如果提升的类型是float or double`,则执行浮点相等测试。

     

请注意,二进制数字促销会执行值集转换和拆箱转换。

因此,请考虑以下事项:

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

这会打印true,因为:

  • 右操作数 是数字int类型
  • 左操作数可转换为数字类型,方法是取消装箱到int
  • 因此==是数字相等操作

摘要

  • 如果==!=的两个操作数都是引用类型,它将始终是引用相等操作
    • 操作数是否可转换为数字类型
    • 无关紧要
  • 如果操作数中至少有一个是数字类型,则它将始终是数字相等操作
    • 如果需要,将在一个(最多!)操作数上自动取消装箱

参考

相关问题