我在下面的一个实例中得到 NullPointerException,而它的对应实例运行平稳。
public static void main(String[] args){
System.out.println(withTernary(null, null)); //Null Pointer
System.out.println(withIfElse(null, null)); //No Exception
}
private static Boolean withTernary(String val, Boolean defVal){
return val == null ? defVal : "true".equalsIgnoreCase(val);
}
private static Boolean withIfElse(String val, Boolean defVal){
if (val == null) return defVal;
else return "true".equalsIgnoreCase(val);
}
Online version
Online version with the lines in main
reversed ,它从 withIfElse
输出 null
,然后在 withTernary
中失败。
我正在使用以下 java 版本
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)
这是来自 the spec (§15.25.2) 的相关引述:
Boolean conditional expressions are standalone expressions (§15.2).
The type of a boolean conditional expression is determined as follows:
If the second and third operands are both of type Boolean
, the conditional expression has type Boolean
.
Otherwise, the conditional expression has type boolean
.
因此,整个表达式的类型被认为是boolean
,Boolean
值被自动拆箱,导致NullPointerException
。
如评论中所述,为什么以下不引发异常?
return val == null ? null : "true".equalsIgnoreCase(val);
好吧,上面的规范摘录仅适用于 boolean 条件表达式,指定为here (§15.25) :
If both the second and the third operand expressions are boolean expressions, the conditional expression is a boolean conditional expression.
For the purpose of classifying a conditional, the following expressions are boolean expressions:
An expression of a standalone form (§15.2) that has type boolean
or Boolean
.
A parenthesized boolean
expression (§15.8.5).
A class instance creation expression (§15.9) for class Boolean
.
A method invocation expression (§15.12) for which the chosen most specific method (§15.12.2.5) has return type boolean
or Boolean
.
(Note that, for a generic method, this is the type before instantiating the method's type arguments.)
A boolean
conditional expression.
因为 null
不是 boolean 表达式,所以整个条件表达式不是 boolean 条件表达式。引用表 15.2(稍后在同一节中),我们可以看到这样的表达式被认为具有 Boolean
类型,因此不会发生拆箱,也不会引发异常。