这个小程序将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
答案 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 "? :")中具体描述。