This threw me.
If you have a Java Long variable and you check equality against a primitive value using the == operator the runtime type of the value is changed to a primitive long.
Subsequent checking the variable for a null value then throws an unexpected NullPointerException.
So in the test class:
public class LongDebug {
public static void main(String[] args) {
Long validValue = 1L;
Long invalidValue = -1L;
Long nullValue = null;
System.out.println("\nTesting the valid value:");
testExpectedBehaviour(validValue);
testUnExpectedBehaviour(validValue);
System.out.println("\nTesting the invalid value:");
testExpectedBehaviour(invalidValue);
testUnExpectedBehaviour(invalidValue);
System.out.println("\nTesting the null value:");
testExpectedBehaviour(nullValue);
testUnExpectedBehaviour(nullValue);
}
/**
* @param validValue
*/
private static void testExpectedBehaviour(Long value) {
if (value == null || value == -1) System.out.println("Expected: The value was null or invalid");
else System.out.println("Expected: The value was valid");
}
private static void testUnExpectedBehaviour(Long value) {
try {
if (value == -1 || value == null) System.out.println("Unexpected: The value was null or invalid");
else System.out.println("Unexpected: The value was valid");
} catch (NullPointerException e) {
System.out.println("Unexpected: The system threw an unexpected NullPointerException");
}
}
}
The result I get is:
Testing the valid value:
Expected: The value was valid
Unexpected: The value was valid
Testing the invalid value:
Expected: The value was null or invalid
Unexpected: The value was null or invalid
Testing the null value:
Expected: The value was null or invalid
Unexpected: The system threw an unexpected NullPointerException
Is this on spec or a bug in the JDK?
This is the problem:
Expressions are evaluated from left to right and since
Longmust be unboxed first, JVM translates this to:And
value.longValue()throwsNullPointerExceptionwhenvalueisnullargument. It never reaches the second part of the expression.It works when the order is different though:
because if the
valueisnull, the second part (that can causeNullPointerExceptionwhenvalueisnull) is never executed due to boolean expression short-circuit evaluation.Of course this is not a bug. The way primitive value wrappers are unboxed is on spec (5.1.8. Unboxing Conversion):
After unboxing is applied, the rest is standard Java.