为什么作为三元运算符编译的结果返回 null(期望布尔值)?

Why does returning null (where a boolean is expected) as the result of a ternary operator compile?

我刚刚注意到的好奇心,而不是问题。

不允许我写

public boolean x() {
  return null;
}

或者这个:

public boolean x() {
  if (DEBUG) {
    return true;
  } else {
    return null;
  }
}

但我可以写

public boolean x() {
  return DEBUG ? true : null;
}

这是为什么? (如果采用 "else" 分支,它似乎会抛出 NPE。)

三元运算符看到您有两个选项 truenull,因此它必须使用自动装箱并自行键入(即 条件运算符的结果) 为 Boolean(这又会被 return 自动拆箱)。

具体规则有点复杂,大家可以自己找in the JLS

在 运行 时,您会在 return 值的拆箱过程中收到 NullPointerException。

jls 所述:

The type of a conditional expression is determined as follows: If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression. If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

这意味着 java 允许 null,因为它可以用来生成 Boolean 的实例,可以拆箱到 boolean(阅读关于boxing 在 jls 中获取更多信息)。但是由于 Boolean 实例被初始化 null,对 booleanValue() 的调用将导致 NullPointerException.

JLS-15.25

The type of a conditional expression is determined as follows: ... If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.

...

At run time, the first operand expression of the conditional expression is evaluated first. If necessary, unboxing conversion is performed on the result.

The resulting boolean value is then used to choose either the second or the third operand expression:

...

The chosen operand expression is then evaluated and the resulting value is converted to the type of the conditional expression as determined by the rules stated above.

This conversion may include boxing (§5.1.7) or unboxing (§5.1.8) conversion.

所以 - 本质上 - 你的 null 被装箱到 Boolean.