new icon example borderfactory java eclipse compilation expression ternary-operator

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 a double

¿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