问题
I like to use the ternary conditional expression in java programming, but I experienced an issue :
The following code is a small example, but it shows the problem that I have found.
public class Example {
public Example() {
Double x = 0.0;
A a = new A();
x = a == null ? 0.0 : a.getY(); // Happens on this line
System.out.println(x);
}
class A {
Double y = null;
private Double getY() {
return y;
}
}
public static void main(String[] args) {
new Example();
}
}
What's causing the NullPointerException
?
回答1:
This results from the JLS rules of determining the type of the ternary conditional expression :
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.
This rule means that the type of the ternary expression is double
and not Double
. Unboxing the Double
returned by your a.getY()
method to double
causes NullPointerException
, since that method returns null
.
a == null ? 0.0 : a.getY();
double Double -> hence the type of the ternary expression is double
回答2:
It happens because 0.0
is of type double
, not Double
. The second two operands to the conditional operator must be of the same type, so autoboxing/unboxing came into it and the compiler turned that code into:
x = Double.valueOf(a == null ? 0.0 : a.getY().doubleValue());
// -^^^^^^^^^^^^^^^--------------------------^^^^^^^^^^^^^^
...which throws because a.getY()
returns null
, and then the code tries to call doubleValue
on null
.
If we run javap -c Example
to decompile the code, we can see those calls (I've put them in bold):
public class Example { public Example(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: dconst_0 5: invokestatic #2 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 8: astore_1 9: new #3 // class Example$A 12: dup 13: aload_0 14: invokespecial #4 // Method Example$A."":(LExample;)V 17: astore_2 18: aload_2 19: ifnonnull 26 22: dconst_0 23: goto 33 26: aload_2 27: invokestatic #5 // Method Example$A.access$000:(LExample$A;)Ljava/lang/Double; 30: invokevirtual #6 // Method java/lang/Double.doubleValue:()D 33: invokestatic #2 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 36: astore_1 37: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 40: aload_1 41: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 44: return public static void main(java.lang.String[]); Code: 0: new #9 // class Example 3: dup 4: invokespecial #10 // Method "":()V 7: pop 8: return }
来源:https://stackoverflow.com/questions/37984033/why-does-a-ternary-conditional-expression-returning-null-and-assigned-to-a-refer