在三元运算符中获取不需要的NullPointerException - 为什么?

Jok*_*ker 48 java double nullpointerexception conditional-operator

在执行以下代码时,我得到一个NullPointerException在线:

value = condition ? getDouble() : 1.0;
Run Code Online (Sandbox Code Playgroud)

在早期的行中,当我使用null而不是getDouble()一切都有效时,这很奇怪.

public class Test {
    static Double getDouble() {
        return null;
    }

    public static void main(String[] args) {
        boolean condition = true;
        Double value;

        value = condition ? null : 1.0;         //works fine
        System.out.println(value);              //prints null

        value = condition ? getDouble() : 1.0;  //throws NPE
        System.out.println(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

有人能帮我理解这种行为吗?

Era*_*ran 77

当你写作

value = condition ? null : 1.0;
Run Code Online (Sandbox Code Playgroud)

类型condition ? null : 1.0必须是引用类型,因此类型是Double,它可以保存值null.

当你写作

value = condition ? getDouble() : 1.0;
Run Code Online (Sandbox Code Playgroud)

getDouble()返回null,它相当于写作:

value = condition ? ((Double) null) : 1.0;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,编译器将a Double和a double视为三元条件运算符的第2和第3个参数,并确定表达式的类型应该是double.因此,unboxes的nulldouble,让NullPointerException.

条件三元运算符的类型由JLS 15.25中的一些表确定.

如果第二和第三操作数nulldouble,条件式类型是最小上界的Doublenull,这是Double.

如果第二个和第三个操作数是Doubledouble,则条件表达式类型是double.

  • 奇怪的.我会对此提出某种票.即使语言标准说编译器应该选择`double`,这也是一个缩小的转换,因为`double`不支持`null`.如果我没记错的话,所有其他隐含的缩小转换都像瘟疫一样被避免.我认为应该改变它以保持一致性. (7认同)

孙兴斌*_*孙兴斌 24

#jls-15.25:

在此输入图像描述

如果第二个操作数是Double,而第三个操作数是 double,结果是:

getCount() == 1 ? getDouble() : 1.0

将是一个double.

当你尝试将一个Double null(返回者getDouble())转换为double,NPE将被抛出.