3

How come this code compiles? I would have expected the compiler to complain about a "Type mismatch: cannot convert from null to boolean" but it doesn't. It just fails with a NullPointerException at runtime.

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)*
Mike
  • 1,390
  • 1
  • 12
  • 17

3 Answers3

3

Java considers the type of ternary expression to be boolean. The compiler treats null as Boolean, i.e. the result of applying a boxing conversion to the primitive type of boolean.

Here is the relevant portion of the language specification:

15.25 The type of a conditional expression is determined as follows:

...

  • If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (ยง5.1.7) to T, then the type of the conditional expression is T.

Language specification states that the boxing/unboxing conversion is applied when necessary to the operand chosen by the condition of the expression. That is what triggers the exception when the code tries to unbox a boolean from null.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

The first part of your ternary determines the operand type, in this case primitive boolean.

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

Note that you can (syntactically) cast a null (which is technically of the NullType) to a boolean, however it results in a NullPointerException. Thus, while the code compiles, if a + b is not equal to 2 you get a NullPointerException. As for why it is syntactically legal, consider

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

Note that Boolean.FALSE is a Boolean, and autounboxing means this code works fine.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
0

This return a + b == 2 ? true : (Boolean) x; is what actually happens, though you can't write that actually, since the compiler will complain. But you could write:

private static boolean whyIsThisPossible(int a, int b) {
    Boolean x = null;
    if (a == b) {
        x = false;
    }
    return a + b == 2 ? true : (Boolean) x;
}
Eugene
  • 117,005
  • 15
  • 201
  • 306