Here's the relevant quote from 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
.
Therefore, the overall expression's type is considered to be boolean
, and the Boolean
value is autounboxed, causing a NullPointerException
.
As mentioned in the comments, why doesn't the following raise an exception?
return val == null ? null : "true".equalsIgnoreCase(val);
Well, the above excerpt from the spec specifically only applies to boolean conditional expressions, which are specified 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.
Since null
is not a boolean expression, the overall conditional expression is not a boolean conditional expression. Referring to Table 15.2 (later in the same section), we can see that such an expression is considered to have a Boolean
type, so no unboxing occurs, and no exception is raised.