为什么Java编译器允许在三元运算符中将null转换为基本类型

时间:2018-04-21 04:33:41

标签: java compiler-errors nullpointerexception runtime-error ternary-operator

这个小程序将NullPointerException抛到三元运算符行:

public class Main {
    int someMethod() {
        return (true ? null : 0);
    }

    public static void main(String[] args)  {
        Main obj= new Main();
        obj.someMethod();
    }
}

我理解原因是null无法投放到int

然而,问题是为什么Java编译器允许传递这种代码,而下面的内容会导致编译时错误:

int i = null; //Error: incompatible types: <nulltype> cannot be converted to int

2 个答案:

答案 0 :(得分:2)

通过Java Language Specification - Conditional Operator,Java将在运行时评估条件表达式,而不是编译时。这就是编译时没有检测到错误的原因:

  

在运行时,首先计算条件表达式的第一个操作数表达式。然后使用结果布尔值来选择第二个或第三个操作数表达式。

所以在你的情况下:

int someMethod() {
    return (true ? null : 0);
}

映像true是一个包含复杂逻辑的方法,如果Java在运行时评估第一个操作数(在本例中为true),则有意义。然后,根据规则:

  

如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,则条件表达式的类型为T. / p>

由于第3个操作数0是原始类型(T),因此表达式的类型为T类型(int)。因此,取消装箱int的空引用将导致NPE。

答案 1 :(得分:0)

编译器不允许

int i = null;

因为表达式null的类型是&#34; null类型&#34;,并且&#34; null类型&#34;没有取消装箱转换规则。 (JLS section 5.1.8)。

但是,允许写:

int i = (Integer) null;

因为表达式(Integer) null具有类型java.lang.Integer并且会导致取消装箱,这总是会导致NullPointerException。

当你写:

return (true ? null : 0);

在返回int的方法中,或者只是在您编写时:

int i = (true ? null : 0);

它编译。 (true ? null : 0)的类型为java.lang.Integer,与int i = (Integer) null;

类似

您应该注意null可以是&#34;盒装&#34;在三元表达式(a ? b : c)的上下文中作为整数,浮点数,双精度等。这在JLS 5.1.7 (boxing conversions)JLS 15.25 (Conditional operator "? :")中具体描述。

相关问题