Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does assigning a null value from a ternary statement to a Boolean variable throw a NPE? [duplicate]

I have a part of code like this:

public static void main(String[] args) throws Exception {
    String trueValue = Boolean.TRUE.toString();
    String fieldValue = null;
    Boolean defaultValue = null;

    Boolean value = (fieldValue != null ? trueValue.equalsIgnoreCase(fieldValue) : defaultValue);

    System.out.println(value);
}

When defaultValue is not equal to null the code works fine, but when defaultValue is null the JVM throws a NullPointerException. This code was compiled using jdk 1.6.45.

Why did I get this exception?

like image 821
Michail Avatar asked Oct 18 '14 19:10

Michail


3 Answers

Java language specification says:

If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

like image 114
Sergii Lagutin Avatar answered Oct 22 '22 03:10

Sergii Lagutin


It's the ternary operator. Because the first option trueValue.equalsIgnoreCase(fieldValue) is a boolean, it seems to assume the second option defaultValue is a boolean rather than a nullable Boolean. It's odd, but that seems to be what's happening. If you cast the first option to Boolean, the error goes away:

Boolean value = (fieldValue != null ? (Boolean) trueValue.equalsIgnoreCase(fieldValue) : defaultValue);
like image 33
khelwood Avatar answered Oct 22 '22 02:10

khelwood


From the JLS: 15.25. Conditional Operator ? :

If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

Aka: when the 2nd and 3rd operand are primitive and boxed reference type, the result is considered the primitive type. At the end of your operation you are boxing it again, but by then you have already tried to assign null to a primitive type - which isn't possible.

The signature of String#equalsIgnoreCase is...

public boolean equalsIgnoreCase
like image 21
Jeroen Vannevel Avatar answered Oct 22 '22 03:10

Jeroen Vannevel