java - 将包装类和原语与 == 运算符进行比较时,类型转换背后的逻辑是什么?
问题描述
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
我的理解是编译器试图i
用Integer.intValue()
. Integer
由于将 Integer 转换为 double ( -> int
-> )需要不止一步,double
编译器拒绝隐式执行,因此我们需要使用显式类型转换来“帮助他”,这将减少步骤数。这是正确的吗?
Integer i = 2;
double d = 2.0;
System.out.println(i == d); // OK: true
在这个例子中,编译器显然需要不止一个步骤来执行转换 ( Integer -> int -> double
)。怎么不抱怨?
我知道必须使用equals()
方法==
解决方案
答案可以在Java Language Specification的第15.21 节中找到。等式运算符:
运算符 ==(等于)和 !=(不等于)称为相等运算符。
如果相等运算符的操作数都是数字类型,或者一个是数字类型而另一个是可转换的(第 5.1.8 节)数字类型,则对操作数执行二进制数字提升(第 5.6 节)。
如果相等运算符的操作数既是引用类型又是 null 类型,则该操作是对象相等。
如果无法通过强制转换(第 5.5 节)将任一操作数的类型转换为另一个操作数的类型,则会出现编译时错误。两个操作数的运行时值必然不相等(忽略两个值都是 的情况
null
)。
如果没有i == d
强制转换,表达式必须遵循 15.21.3 节中的规则,因为i
和d
都是引用类型,而不是数字类型。只有原始类型是数字类型(boolean
当然除外)。
由于 anInteger
不能转换为 a Double
,并且 aDouble
不能转换为 an Integer
,编译器知道表达式不可能为真(忽略两个值都是 的情况null
),因此会发生编译类型错误。
当您这样做(double) i == d
时,左侧将变为数字类型,并适用第 15.21.1 节中指定的规则。
推荐阅读
- amazon-web-services - 像 s3 的 OverlayFS 之类的东西?
- apache-flink - 如何将 Flink 连接到在另一台机器上运行的 Kafka?
- jsonschema - 如何将附加属性:false 应用于所有对象?
- ssl - 使用服务器密钥签署客户端证书时出现无法加载证书错误
- reactjs - 从 M91 开始,SharedArrayBuffer 将需要跨域隔离,大约在 2021 年 5 月
- c - 使用多维 char 数组时数据损坏
- amazon-web-services - SonarQube 没有在 EFS 上使用 AWS EKS Fargate
- outlook-2016 - 是否可以在使用 Outlook 2016 发送的电子邮件中附加和嵌入小视频?
- angular - 为什么 Identity Server logoutId 总是为空?
- swift - 如何在 iOS 网络扩展中解析数据包