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
nulladouble
¿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