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

pol*_*nts 25 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"
Run Code Online (Sandbox Code Playgroud)

很明显为什么最后一行总是打印出来"false":我们正在使用==引用标识比较,而new对象永远不会==已经存在的对象.

问题是前三行:那些比较保证在原语上int,Integer自动取消装箱?是否存在基元将被自动装箱的情况,并且执行参考标识比较?(那就是全部false!)

Mat*_*hen 20

是. 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类型,则操作是对象相等

这符合拳击和拆箱的共同理解,只有在不匹配时才会这样做.


pol*_*nts 7

我将首先准确地 解释何时==是引用相等,并且恰好是何时它是数字相等.参考相等的条件更简单,因此首先解释.

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

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

这解释了以下内容:

System.out.println(new Integer(0) == new Integer(0)); // "false"
Run Code Online (Sandbox Code Playgroud)

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

为了==是数字相等,至少有一个操作数必须是数字类型 ; 这个规定如下:

JLS 15.21.1数值等式算子==!=

如果相等运算符的操作数是两个数字类型的,或一个是数字类型的,并且另一种是可转换到数字类型,二进制数值提升时对操作数执行.如果操作数的提升类型是intlong,则执行整数相等测试; 如果提升的类型是float ordouble`,则执行浮点相等测试.

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

因此,请考虑以下事项:

System.out.println(new Integer(0) == 0); // "true"
Run Code Online (Sandbox Code Playgroud)

这打印true,因为:

  • 右操作数数字int类型
  • 通过取消装箱,左操作数可转换为数字类型int
  • 因此==是数字相等运算

摘要

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

参考

相关问题