首页 > 解决方案 > 将包装类和原语与 == 运算符进行比较时,类型转换背后的逻辑是什么?

问题描述

int -> double -> Double我读到编译器在执行隐式转换(或)需要多个操作时拒绝使用自动装箱/拆箱Integer -> int -> double。还是比较混乱

Integer i = 2;
Double d = 2.0;
System.out.println(i == d); // COMPILE TIME ERROR

// fix

System.out.println( (double) i == d); // OK: true

我的理解是编译器试图iInteger.intValue(). Integer由于将 Integer 转换为 double ( -> int-> )需要不止一步,double编译器拒绝隐式执行,因此我们需要使用显式类型转换来“帮助他”,这将减少步骤数。这是正确的吗?

Integer i = 2;
double d = 2.0;
System.out.println(i == d); // OK: true

在这个例子中,编译器显然需要不止一个步骤来执行转换 ( Integer -> int -> double)。怎么不抱怨?

我知道必须使用equals()方法==

标签: javawrapperautoboxingtype-promotion

解决方案


答案可以在Java Language Specification的第15.21 节中找到。等式运算符

运算符 ==(等于)和 !=(不等于)称为相等运算符。

15.21.1 节。数值等式运算符==!=说:

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

15.21.3 节。参考相等运算符==!=说:

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

如果无法通过强制转换(第 5.5 节)将任一操作数的类型转换为另一个操作数的类型,则会出现编译时错误。两个操作数的运行时值必然不相等(忽略两个值都是 的情况null)。

如果没有i == d强制转换,表达式必须遵循 15.21.3 节中的规则,因为id都是引用类型,而不是数字类型。只有原始类型是数字类型boolean当然除外)。

由于 anInteger不能转换为 a Double,并且 aDouble不能转换为 an Integer,编译器知道表达式不可能为真(忽略两个值都是 的情况null),因此会发生编译类型错误。

当您这样做(double) i == d时,左侧将变为数字类型,并适用第 15.21.1 节中指定的规则。


推荐阅读