Это связано с autoboxing и autounboxing. Если вы посмотрите на байт-код (см. Ниже), вы можете позвонить по номеру Double.valueOf
(бокс 3.7d
) и Double#doubleValue
(распаковка результата условного выражения). Операнды к условному оператору должен быть того же типа, так что компилятор эффективно превращая ваш код в это:
public double getSomeDouble() {
return ("" != null ? Double.valueOf(3.7d) : null).doubleValue();
}
... потому что Double
наиболее специфичен распространенный тип он может найти для 3.7d
и null
.
Я использовал строковый аргумент (для устранения оптимизации компилятора вокруг инвариантного выражения "" != null
, что компилятор смог бы сказать, никогда не будет правдой):
public double getSomeDouble(String str) {
return str != null ? 3.7d : null;
}
, который эффективно становится:
public double getSomeDouble(String str) {
return (str != null ? Double.valueOf(3.7d) : null).doubleValue();
}
... и действительно получил NPE во время работы, когда я прошел в null
для str
, когда он пытался позвонить doubleValue()
по телефону null
.
Вот байткод для моего getSomeDouble(String)
(от javap -c MyClass
): [? Относящиеся]
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