为什么三元运算给出零点,而它的 ifelse 对应物却没有?

我在下面的一个实例中得到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);
}

在线版

在线版本,线反转,从 中输出,然后在 中失败。nullwithIfElsewithTernary

我正在使用下面的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)

答案 1

以下是规范 (§15.25.2) 中的相关引用:

布尔条件表达式是独立的表达式 (§15.2)。

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

  • 如果第二个和第三个操作数都是类型,则条件表达式具有 类型 。BooleanBoolean

  • 否则,条件表达式的类型为 。boolean

因此,整个表达式的类型被视为 ,并且该值被自动取消框,从而导致 .booleanBooleanNullPointerException


正如评论中提到的,为什么以下没有提出异常?

return val == null ? null : "true".equalsIgnoreCase(val);

好吧,上面从规范中摘录的内容特别适用于布尔条件表达式,此处指定了这些表达式 (§15.25)

如果第二个和第三个操作数表达式都是布尔表达式,则条件表达式是布尔条件表达式。

出于对条件进行分类的目的,以下表达式是布尔表达式:

  • 具有类型 或 的独立形式 (§15.2) 的表达式。booleanBoolean

  • 带括号的表达式 (§15.8.5)。boolean

  • 类 的类实例创建表达式 (§15.9) 。Boolean

  • 一种方法调用表达式 (§15.12),为其选择的最具体的方法 (§15.12.2.5) 返回类型 或 。
    (请注意,对于泛型方法,这是实例化方法的类型参数之前的类型。booleanBoolean

  • 条件表达式。boolean

由于 不是布尔表达式,因此整个条件表达式不是布尔条件表达式。参考表 15.2(在同一节的后面部分),我们可以看到这样的表达式被视为具有类型,因此不会发生取消装箱,也不会引发异常。nullBoolean


答案 2

val == null ? defVal : "true".equalsIgnoreCase(val)- 在此表达式中,第三个参数是 ,并且由于三元运算符必须具有一个静态类型,因此它将尝试取消装箱 ,因此 NPE。只有 分配 到 将再次导致拳击。检查一下booleannullBoolean