java - icon - La expresión ternaria a veces pasa por alto las comprobaciones del compilador
my icon java (1)
Por alguna razón, el siguiente código compila normalmente:
public double getSomeDouble() {
return "" != null ? 3.7d : null;
}
Normalmente espero que Eclipse marque como un error (el null
no se puede convertir en una double
primitiva).
Solo para respaldar mi suposición, este código no funcionaría:
public double getSomeDouble() {
return null;
}
Eclipse marcaría la línea return null
como error, indicando:
No coincide el tipo: no se puede convertir de
null
adouble
¿Por qué no dice lo mismo en el fragmento de código anterior?
Se debe al autoboxing y autounboxing . Si observa el Double.valueOf
de Double.valueOf
(a continuación), puede ver las llamadas a Double.valueOf
(boxing the 3.7d
) y Double#doubleValue
(unboxing el resultado de la expresión condicional). Los operandos del operador condicional deben ser del mismo tipo, por lo que el compilador está convirtiendo efectivamente su código en esto:
public double getSomeDouble() {
return ("" != null ? Double.valueOf(3.7d) : null).doubleValue();
}
... porque Double
es el tipo común más específico que puede encontrar para 3.7d
y null
.
Utilicé un argumento de cadena (para eliminar la optimización del compilador alrededor de la expresión invariante "" != null
, lo que el compilador podría decir que nunca sería verdadero):
public double getSomeDouble(String str) {
return str != null ? 3.7d : null;
}
que efectivamente se convierte en:
public double getSomeDouble(String str) {
return (str != null ? Double.valueOf(3.7d) : null).doubleValue();
}
... y de hecho obtuve una NPE en tiempo de ejecución cuando pasé null
for str
, cuando intentó llamar a doubleValue()
en null
.
Aquí está el getSomeDouble(String)
para mi getSomeDouble(String)
(de 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