Jest to spowodowane autoboxing i autounboxing. Jeśli spojrzysz na kod bajtowy (poniżej), możesz zobaczyć połączenia z Double.valueOf
(boxing the 3.7d
) i Double#doubleValue
(rozpakowywanie wyniku wyrażenia warunkowego). Argumenty do operatora warunkowego musi być tego samego typu, więc kompilator jest skutecznie odwracając swój kod na to:
public double getSomeDouble() {
return ("" != null ? Double.valueOf(3.7d) : null).doubleValue();
}
... bo Double
jest najbardziej rozpowszechnionym typem specyficzny może znaleźć dla 3.7d
i null
.
użyłem argumentu ciąg (w celu wyeliminowania optymalizacji kompilatora wokół niezmiennego wyrazu "" != null
, które kompilator będzie w stanie powiedzieć, że nigdy nie było prawdziwe):
public double getSomeDouble(String str) {
return str != null ? 3.7d : null;
}
które skutecznie staje:
public double getSomeDouble(String str) {
return (str != null ? Double.valueOf(3.7d) : null).doubleValue();
}
... i rzeczywiście uzyskałem NPE w czasie pracy, gdy zdałem null
dla str
, kiedy próbowałem zadzwonić pod numer doubleValue()
pod numerem null
.
Oto kod bajtowy dla mojego getSomeDouble(String)
(od javap -c MyClass
): [? Podobne]
public double getSomeDouble(java.lang.String);
Code:
0: aload_1
1: ifnull 13
4: ldc2_w #7 // double 3.7d
7: invokestatic #9 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
10: goto 14
13: aconst_null
14: invokevirtual #10 // Method java/lang/Double.doubleValue:()D
17: dreturn
(http://stackoverflow.com/q/8098953/1391249) – Tiny