当return使用三元运算符时,返回布尔值的方法怎么仍然编译?

时间:2017-12-01 02:41:46

标签: java

为什么这段代码会编译?我原以为编译器会抱怨"类型不匹配:无法从null转换为布尔值"但它并没有。它只是在运行时失败并出现NullPointerException。

public static void main(String[] args) throws Exception {
    System.out.println("this throws a NPE: " + whyIsThisPossible(1, 2));
}

private static boolean whyIsThisPossible(int a, int b) {
    return a + b == 2 ? true : null;
}

Exception in thread "main" java.lang.NullPointerException
at FunkyMethodTest.whyIsThisPossible(FunkyMethodTest.java:10)
at FunkyMethodTest.main(FunkyMethodTest.java:5)*

3 个答案:

答案 0 :(得分:3)

Java认为三元表达式的类型为boolean。编译器将null视为Boolean,即将装箱转换应用于原始类型boolean的结果。

以下是语言规范的相关部分:

  

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

     

...

     
      
  • 如果第二个和第三个操作数之一是基本类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,那么类型条件表达式是T
  •   

语言规范指出装箱/取消装箱转换在必要时应用于由表达式条件选择的操作数。这是代码尝试从boolean取消装箱null时触发异常的原因。

答案 1 :(得分:0)

三元组的第一部分确定操作数类型,在本例中为原始boolean

return a + b == 2 ? true : null;

请注意,您可以(语法上)将null(技术上为NullType)转换为boolean,但会产生NullPointerException。因此,在代码编译时,如果a + b不等于2,则会得到NullPointerException。至于为什么它在语法上是合法的,请考虑

return a + b == 2 ? true : Boolean.FALSE;

请注意,Boolean.FALSEBoolean,自动装箱意味着此代码正常运行。

答案 2 :(得分:0)

这个return a + b == 2 ? true : (Boolean) x;实际发生了,虽然你实际上写不出来,因为编译器会抱怨。但你可以写:

private static boolean whyIsThisPossible(int a, int b) {
    Boolean x = null;
    if (a == b) {
        x = false;
    }
    return a + b == 2 ? true : (Boolean) x;
}