一尘不染

NullPointerException通过Java三元运算符的自动装箱行为

java

NullPointerException几天,我因三元运算符中意外的类型转换而遇到了一个非常奇怪的问题。鉴于此(无用的示例性)功能:

Integer getNumber() {
    return null;
}

我期望编译后以下两个代码段完全相同:

Integer number;
if (condition) {
    number = getNumber();
} else {
    number = 0;
}

Integer number = (condition) ? getNumber() : 0;

事实证明,如果conditiontrue,则if-statement可以正常工作,而第二个代码段中的三元运算则抛出a
NullPointerException。似乎三元运算已决定将这两种选择都强制转换为类型,int然后再将结果自动装箱为Integer!?!。实际上,如果我将显式转换0Integer,则该异常消失。换一种说法:

Integer number = (condition) ? getNumber() : 0;

与以下内容不同:

Integer number = (condition) ? getNumber() : (Integer) 0;

因此,似乎三元运算符和等效if- else语句之间存在字节码差异(这是我没想到的)。这就提出了三个问题:为什么会有区别?这是三元实现中的错误还是类型转换的原因?鉴于存在差异,三元运算的性能是否比等效if语句高(或低)(我知道,差异不可能很大,但仍然可以)?


阅读 227

收藏
2020-09-08

共1个答案

一尘不染

根据JLS

条件表达式的类型确定如下:

  • 如果第二个操作数和第三个操作数具有相同的类型(可能为null类型),则这是条件表达式的类型。
  • 如果第二个操作数和第三个操作数之一是原始类型T,而另一个操作数的类型是对T应用装箱转换
    (第5.1.7节)的结果,则条件表达式的类型为T。
2020-09-08