Question

I recently tried to run the following two snippets of code and was surprised at the output.

First:

// ...
System.out.println( (Boolean)null || true );
// ...

Second:

// ...
System.out.println( (Boolean)null || false );
// ...

The first example results in the following output:
true

The second example results in the following output:
Exception in thread "main" java.lang.NullPointerException
   at com.blah.main(SanityCheck.java:26)

I would have thought both examples should result in a null pointer exception, as any short-circuiting is applied left-to-right. The attempt to unbox the boolean from the Boolean should have failed before the other side of the logical or was given consideration.

Can anyone explain this inconsistent behaviour?

Was it helpful?

Solution 2

I'll take a jab at it. As the compiler attempts to interpret the two statements, the main difference is that the statement with true on the right side is not required to make a computation with the left handed Boolean, while the statement with false on the right side is.

A Boolean is an Object, thus it can be set to null. That is not where the exception is thrown. The NullPointerException is thrown when you attempt to execute an operation on a Boolean object that is set to null. In the true case, the compiler will pass casting null to a Boolean, and because OR'ing with true will always yield true, the conditional is true. In the false case, the compiler will pass casting null to a Boolean again, it will then check false, and if the condition is false, it needs to compute the OR with the Boolean because the condition could ultimately come out as true or false. When the computation happens, the NullPointerException is thrown.

OTHER TIPS

I ran the class file through JAD to see what the optimised code looked like. For the true case:

// ...
System.out.println(true);
// ...

For the false case:

// ...
System.out.println(null.booleanValue());
// ...

I cannot reproduce your results. I actually get NPE for both cases.

As per JLS, the left-hand operand expression is always evaluated first. When (Boolean)null is evaluated, an auto unboxing is performed on a null Boolean object. In particular, the underlying code null.booleanValue() is causing the NPE.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top