variable the operator java ternary-operator

java - the - ternary operator python



Comportamiento extraño de condicional ternario con tipos encajonados en Java (5)

Esta pregunta ya tiene una respuesta aquí:

Tenía esta pieza de código en mi aplicación (versión simplificada):

Object result; if (check) result = new Integer(1); else result = new Double(1.0); System.out.println(result); return result;

Entonces decidí refactorizar la sentencia if-else a una expresión condicional ternaria para que mi código sea más conciso:

Object result = check ? new Integer(1) : new Double(1.0); System.out.println(result); return result;

Resultó que en caso de que la verificación fuera true las dos versiones imprimen resultados diferentes:

1

o:

1.0

¿No es el condicional ternario equivalente al correspondiente if-else?


Además de la respuesta @ pb2q

puedes verificarlo como

public class test { public static void main(String[] args) { Object result; Boolean check = true; if (check) result = new Integer(1); else result = new Double(1.0); System.out.println(result); result = check ? new Integer(2) : new Double(1.0); System.out.println(result); } }

imprimirá 2.0 en lugar de 2 debido a la promoción numérica


Además de las respuestas existentes, puede evitar el problema mediante la conversión específica al tipo que desee:

Object result = args.length < 100 ? (Object)2 : (Object)1.0;

Convertir en cuadros de Object el entero como un entero y el doble como un doble. Las expresiones a cada lado de ":" son de tipo Object , por lo que el compilador no necesita generar más conversiones.


En pocas palabras, el operador ternario no es diferente de otros operadores en lo que se refiere a la promoción de tipo numérico.

Cuando tiene algo como System.out.println(1 + 1.0) , espera que se imprima 2.0 , porque los operandos utilizados en la salida están sujetos a promociones de tipo numérico.

Es exactamente lo mismo con el operador ternario: System.out.println(true ? 1 : 1.0) imprimirá 1.0 después de hacer las mismas promociones de tipo numérico que habría hecho si la expresión fuera 1 + 1.0 .

Funciona de esa manera por una razón muy simple: el tipo de resultado del operador debe ser conocido en tiempo de compilación, mientras que su resultado real se determina en tiempo de ejecución.


La expresión if / else y la condicional (ternaria) no son del todo equivalentes. El resultado de la expresión condicional debe tener un tipo.

Estás observando los efectos de la promoción de tipo numérico (o la coacción de tipo).

Aquí hay un extracto de la especificación de idioma (ver here ), de la sección que describe el valor de retorno de la expresión condicional:

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:

El caso final es (omití los otros casos aquí):

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.

Aquí está la especificación adicional relacionada con la promoción numérica binaria:

La conversión de la primitiva de ampliación (§5.1.2) se aplica para convertir uno o ambos operandos según lo especificado por las siguientes reglas:

  • Si cualquiera de los operandos es de tipo doble, el otro se convierte en doble.

Es el primer caso (se omiten los siguientes casos). double siempre gana.

Por lo tanto, independientemente del orden de los operandos segundo y tercero en su expresión condicional, el tipo de retorno de la expresión se promoverá al double .


Respuesta corta

El primer ejemplo escrito explícitamente como Object , lo que causa un upcast.

El segundo ejemplo se escribe implícitamente como Double , lo que causa una ampliación numérica.

Respuesta larga

En el ejemplo con Object , no hay conversión de valores, solo un upcast, y se imprime 1.

Object result; if (1 == 1) result = new Integer(1); else result = new Double(1.0);

Si en su lugar declara usar Double , sería una ampliación e impresión 1.0.

Double result; if (1 == 1) result = new Integer(1); else result = new Double(1.0);

Estos son bastante sencillos ya que hay un tipo explícito.

Sin embargo, la expresión ternaria no tiene un tipo explícito y las reglas no son triviales.

El tipo de una expresión condicional se determina de la siguiente manera:

  • Si el segundo y tercer operandos tienen el mismo tipo (que puede ser el tipo nulo), entonces ese es el tipo de la expresión condicional.

  • Si uno de los operandos segundo y tercero es de tipo primitivo T, y el tipo del otro es el resultado de aplicar la conversión de boxeo (§5.1.7) a T, entonces el tipo de la expresión condicional es T.

  • Si uno de los operandos segundo y tercero es del tipo nulo y el tipo del otro es un tipo de referencia, entonces el tipo de la expresión condicional es ese tipo de referencia.

  • 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:

    • Si uno de los operandos es de tipo byte o Byte y el otro es de tipo corto o Corto, entonces el tipo de expresión condicional es corto.

    • Si uno de los operandos es de tipo T, donde T es byte, short o char, y el otro es una expresión constante (§15.28) de tipo int cuyo valor es representable en el tipo T, entonces el tipo de expresión condicional es T.

    • Si uno de los operandos es de tipo T, donde T es Byte, Corto o Carácter, y el otro es una expresión constante (§15.28) de tipo int cuyo valor es representable en el tipo U que es el resultado de aplicar unboxing conversión a T, entonces el tipo de expresión condicional es U.

    • 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. Tenga en cuenta que la promoción numérica binaria realiza la conversión del conjunto de valores (§5.1.13) y puede realizar la conversión de unboxing (§5.1.8).

  • De lo contrario, el segundo y tercer operandos son de los tipos S1 y S2, respectivamente. Deje que T1 sea el tipo que resulta de aplicar la conversión de boxeo a S1, y que T2 sea el tipo que resulta de aplicar la conversión de boxeo a S2. El tipo de expresión condicional es el resultado de aplicar la conversión de captura (§5.1.10) a lub (T1, T2) (§15.12.2.7).

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25

El "tipo promovido" de números Integer y Double es Double .