将包装器 类 和原语与 == 运算符进行比较时,类型转换背后的逻辑是什么?

What is the logic behind type conversion when comparing wrapper classes and primitives with == operator?

我读到编译器拒绝使用自动 boxing/unboxing 当需要多个操作来执行隐式转换(int -> double -> DoubleInteger -> 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

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

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

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

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

答案可以在Java Language Specification, in section 15.21. Equality Operators中找到:

The operators == (equal to) and != (not equal to) are called the equality operators.

15.21.1. Numerical Equality Operators == and != 节说:

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6).

15.21.3. Reference Equality Operators == and != 节说:

If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.

It is a compile-time error if it is impossible to convert the type of either operand to the type of the other by a casting conversion (§5.5). The run-time values of the two operands would necessarily be unequal (ignoring the case where both values are null).

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

由于 Integer 不能转换为 Double,并且 Double 不能转换为 Integer,编译器知道这是不可能的表达式为真(忽略两个值都是 null 的情况),因此发生 compile-type 错误。

当您执行 (double) i == d 时,left-hand 侧变为数字类型,并适用第 15.21.1 节中指定的规则。