¿Por qué el operador ternario lanza inesperadamente números enteros?

Lo he visto discutido en alguna parte que el siguiente código da como resultado que obj sea ​​un Double , pero que imprime 200.0 desde el lado izquierdo.

 Object obj = true ? new Integer(200) : new Double(0.0); System.out.println(obj); 

Resultado: 200.0


Sin embargo, si coloca un objeto diferente en el lado derecho, p. Ej. BigDecimal , el tipo de obj es Integer como debería ser.

 Object obj = true ? new Integer(200) : new BigDecimal(0.0); System.out.println(obj); 

Resultado: 200


Supongo que la razón de esto tiene que ver con lanzar el lado izquierdo a un double del mismo modo que ocurre para las comparaciones y cálculos integer / double , pero aquí los lados izquierdo y derecho no interactúan de esta manera.

¿Por qué pasó esto?

Debe leer la sección 15.25 de la Especificación del lenguaje Java .

En particular:

De lo contrario, si el segundo y tercer operandos 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 short o short, 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 operando es una expresión constante de tipo int cuyo valor es representable en tipo T, entonces> – el tipo de expresión condicional es T.
  • Si uno de los operandos es de tipo Byte y el otro operando es una expresión constante de tipo int cuyo valor es representable en tipo byte, entonces el tipo de expresión condicional es byte.
  • Si uno de los operandos es de tipo Short y el otro operando es una expresión constante de tipo int cuyo valor es representable en tipo short, entonces el tipo de expresión condicional es corto.
  • Si uno de los operandos es de tipo; El carácter y el otro operando es una expresión constante de tipo int cuyo valor es representable en tipo char, luego el tipo de expresión condicional es char.
  • 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 del segundo y tercer operandos. Tenga en cuenta que la promoción numérica binaria realiza la conversión de unboxing (§5.1.8) y la conversión de conjuntos de valores (§5.1.13).

Entonces se aplica la promoción numérica binaria , que comienza con:

Cuando un operador aplica la promoción numérica binaria a un par de operandos, cada uno de los cuales debe denotar un valor que es convertible a un tipo numérico, las siguientes reglas se aplican, en orden, usando conversión de ampliación (§5.1.2) para convertir operandos según sea necesario :

  • Si alguno de los operandos es de un tipo de referencia, se realiza la conversión de unboxing (§5.1.8). Entonces:
  • Si cualquiera de los dos operandos es del tipo double, el otro se convierte a double.

Eso es exactamente lo que sucede aquí: los tipos de parámetros se convierten a int y double respectivamente, el segundo operando (el tercero en la expresión original) es entonces de tipo double , por lo que el tipo de resultado general es double .

Conversión numérica en el operador condicional? :

En el operador condicional a ? b : c , si tanto c son tipos numéricos diferentes, las siguientes reglas de conversión se aplican en tiempo de comstackción para hacer que sus tipos sean iguales , en orden:

  • Los tipos se convierten a sus primitivos correspondientes, lo que se denomina unboxing .

  • Si un operando era una constante int (no Integer antes de unboxing) cuyo valor es representable en el otro tipo, el int operando se convierte en el otro tipo.

  • De lo contrario, el tipo más pequeño se convierte en el siguiente más grande hasta que ambos operandos tengan el mismo tipo. Las órdenes de conversión son:
    byte -> short -> int -> long -> float -> double
    char -> int -> long -> float -> double

Eventualmente, toda la expresión condicional obtiene el tipo de su segundo y tercer operandos.

Ejemplos:
Si combina char con short , la expresión se convierte en int .
Si combina Integer con Integer , la expresión se convierte en Integer .
Si combina final int i = 5 con un Character , la expresión se convierte en char .
Si combina short con float , la expresión se vuelve float .

En el ejemplo de la pregunta, 200 se convierte de Integer en double , 0.0 se desempaqueta de Double en double y toda la expresión condicional se convierte en double que finalmente se encapsula en Double porque obj es de tipo Object .