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

请考虑以下代码段:

    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行:这些比较是否保证在原始,自动解装箱?是否存在原语将被自动装箱并执行引用标识比较的情况?(这将是所有的话!intIntegerfalse


答案 1

是的。JLS §5.6.2 指定二进制数字提升的规则。部分地:

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

如果任何操作数属于引用类型,则执行取消装箱转换 (§5.1.8)。

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

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

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

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

如果相等运算符的操作数既是引用类型又是 null 类型,则该操作是对象相等

这符合对拳击和拆箱的普遍理解,只有当不匹配时才会这样做。


答案 2

我将首先准确地解释何时是参考相等,以及何时是数字相等。参考相等的条件更简单,因此将首先对其进行解释。==

JLS 15.21.3 参考相等运算符 ==!=

如果相等运算符的操作数既是引用类型又是 null 类型,则该操作是对象相等。

这解释了以下内容:

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

两个操作数都是 ,它们是引用类型,这就是为什么引用相等比较,并且两个对象永远不会彼此对应,所以这就是它打印的原因。Integer==new==false

对于数字相等,至少一个操作数必须是数字类型;这指定如下:==

JLS 15.21.1 数值相等运算符 ==!=

如果相等运算符的操作数都是数值类型,或者一个是数值类型,另一个是可转换为数值类型,则对操作数执行二进制数值提升。如果操作数的提升类型为 或 ,则执行整数相等性检验;如果提升的类型为双精度',则执行浮点相等性检验。intlongfloat or

请注意,二进制数值提升会执行值集转换和拆箱转换。

因此,请考虑以下事项:

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

这将打印 ,因为:true

  • 正确的操作数数值类型int
  • 左操作数可转换为数值类型,方法是取消装箱int
  • 因此是数值相等运算==

总结

  • 如果 和 的两个操作数都是引用类型,则它将始终是引用相等操作==!=
    • 操作数是否可以转换为数值类型并不重要
  • 如果至少有一个操作数是数值类型,则它将始终是数值相等运算
    • 如有必要,将对一个(最多!)操作数执行自动开箱

引用

相关问题


推荐