Java's ternary operator, wrappers & NPE's
Don’t mix wrapper types and primitives inside a ternary operator.
The following method returns one of its parameters depending on the given condition…
Integer select(boolean condition, Integer wrapped, int primitive) {
if (condition) {
return wrapped;
} else {
return primitive;
}
}
…and is invoked as follows:
Integer selected = select(condition, wrapped, primitive);
You might be tempted to replace the whole method by using Java’s ternary operator instead:
Integer selected = condition ? wrapped : primitive;
However, this simple refactoring will result in a NullPointerException if the value of wrapped
is null. This is because for some reason, the Java Language Specification demands that if a ternary operator has operands of type Integer and int, then the resulting type must be of type int (and not Integer, like our previous “select” method). As a consequence, even if we assign the result of the ternary expression to an Integer, Java first tries to unbox the wrapped Integer variable, which might trigger a NullPointerException.
To prevent this, you have to manually infer that the primitive value will eventually be boxed anyway:
Integer selected = condition ? wrapped : Integer.valueOf(primitive);
With these parameter types (both Integer), Java uses Integer as the ternary expression’s result type, and doesn’t try to unbox the wrapped variable any longer.