triple the statement operator not elvis java if-statement return ternary-operator

statement - the ?:operator in java



Tipo de retorno "incorrecto" cuando se usa if vs. ternary opertator en Java (2)

Además de la respuesta de @Jon, mirando el código de bytes que ve:

public static java.lang.Object getWithQuestionMark(); Code: 0: getstatic #7; //Field doubleValue:Ljava/lang/Double; 3: ifnonnull 16 6: getstatic #8; //Field longValue:Ljava/lang/Long; 9: invokevirtual #9; //Method java/lang/Long.longValue:()J 12: l2d 13: goto 22 16: getstatic #7; //Field doubleValue:Ljava/lang/Double; 19: invokevirtual #10; //Method java/lang/Double.doubleValue:()D 22: invokestatic #11; //Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 25: astore_0 26: aload_0 27: areturn

Mientras que si le dices al compilador que no estás interesado en los números:

public static Object getWithQuestionMark() { return doubleValue == null ? (Object)longValue : (Object)doubleValue; }

obtendrás lo que estabas buscando (bytecode)

public static java.lang.Object getWithQuestionMark(); Code: 0: getstatic #7; //Field doubleValue:Ljava/lang/Double; 3: ifnonnull 12 6: getstatic #8; //Field longValue:Ljava/lang/Long; 9: goto 15 12: getstatic #7; //Field doubleValue:Ljava/lang/Double; 15: areturn

salidas:

$ java IfTest class java.lang.Long class java.lang.Long

En la siguiente clase, el tipo de retorno de los dos métodos es inconsistente con la idea de que el operador ternario:

return condition?a:b;

es equivalente a

if(condition) { return a; } else{ return b; }

El primero devuelve un Doble y el segundo un Largo:

public class IfTest { public static Long longValue = 1l; public static Double doubleValue = null; public static void main(String[] args) { System.out.println(getWithIf().getClass());// outpus Long System.out.println(getWithQuestionMark().getClass());// outputs Double } public static Object getWithQuestionMark() { return doubleValue == null ? longValue : doubleValue; } public static Object getWithIf() { if (doubleValue == null) { return longValue; } else { return doubleValue; } } }

Me imagino que esto tiene que ver con el compilador de conversión angosta del tipo de retorno de getWithQuestionMark() pero, ¿es correcto el lenguaje? Ciertamente no es lo que hubiera esperado.

Cualquier información más bienvenida!

Edición: hay muy buenas respuestas a continuación. Además, la siguiente pregunta a la que hace referencia @sakthisundar explora otro efecto secundario de la promoción de tipo que se produce en el operador ternario: operador ternario complicado en Java - autoboxing


Básicamente sigue las reglas de la sección 15.25 de JLS , específicamente:

De lo contrario, si los operandos segundo y tercero tienen tipos que son convertibles (§5.1.8) a tipos numéricos, entonces hay varios casos:

  • [...]

  • De lo contrario, la promoción numérica binaria (§5.6.2) se aplica a los tipos de operandos, y el tipo de expresión condicional es el tipo promovido de los operandos segundo y tercero.

Por lo tanto , se sigue la sección 5.6.2 , que básicamente implica desempaquetar, por lo que hace que su expresión funcione como si longValue y doubleValue fueran de tipo long y double respectivamente, y la promoción de ampliación se aplica al long para obtener un tipo de resultado general de double .

Ese double se encuadra para devolver un Object del método.