A few days ago, I ran into a fascinating scenario that I couldn't find any documentation on how or why Java lets the following happen. (This snippet is just a simplified form of the bug.)
@Test
public void test() {
boolean bool = false;
Integer intVal = Integer.valueOf(5);
Long longVal = null;
Long result = bool ? intVal : longVal;
System.out.println(" > " + result);
}
in the snippet above:
if the bool = true, then you get the value '5';
but if bool = false, then you get a null pointer exception when trying to evaluate the ternary operation. NOT the print statement.
To fix this I just change 'result' to
Long result = bool ? Long.valueOf(intVal) : longVal;
Doing this, will give the expected behavior I needed:
if the bool = true, then you get the value '5';
but if bool = false, then you get 'null'
now the fun part is that if you split this into a normal if/else statement, then java does NOT let you compile
longVal = intVal;
but it doesnt catch that via the ternary operator. So what's Java doing to make it null point in the original snippet?
(java 11)
When you do this:
Long result = bool ? intVal : longVal
This expression is returning a long
and, when bool
is false it tries to unboxe null
to a Long value to fit the result
variable and throws a NPE.
When you do this:
Long result = bool ? Long.valueOf(intVal) : longVal
This expression is already returning Long
then there is no need for unboxing and the null
value is successfully assigned to the result
variable.
Reference:
As discussed in the comments section, to better understand why does this happen, check the following sections of the JLS:
- Section 5.6.2: Binary Numeric Promotion
- Section 15.25: Conditional Operator ? :