¿Se garantiza que el nuevo entero (i) == i en Java?

Considere el siguiente fragmento:

int i = 99999999; byte b = 99; short s = 9999; Integer ii = Integer.valueOf(9); // should be within cache System.out.println(new Integer(i) == i); // "true" System.out.println(new Integer(b) == b); // "true" System.out.println(new Integer(s) == s); // "true" System.out.println(new Integer(ii) == ii); // "false" 

Es obvio por qué la última línea SIEMPRE imprime "false" : estamos usando == comparación de identidad de referencia, y un new objeto NUNCA será == para un objeto ya existente.

La pregunta es sobre las primeras 3 líneas: ¿están garantizadas las comparaciones en la primitiva int , con el Integer auto-unboxed? ¿Hay casos en los que la primitiva se autocasete en su lugar, y se realizan comparaciones de identidad de referencia? (¡lo que entonces sería false !)

Sí. JLS §5.6.2 especifica las reglas para la promoción numérica binaria. En parte:

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).

La promoción numérica binaria se aplica a varios operadores numéricos, incluidos “los operadores de igualdad numérica == y! =”.

JLS §15.21.1 (Operadores de igualdad numérica == y! =) Especifica:

Si los operandos de un operador de igualdad son ambos de tipo numérico, o uno es de tipo numérico y el otro es convertible (§5.1.8) a tipo numérico, se realiza una promoción numérica binaria en los operandos (§5.6.2).

Por el contrario, JLS §15.21.3 (Operadores de igualdad de referencia == y! =) Proporciona:

Si los operandos de un operador de igualdad son de tipo de referencia o nulo, entonces la operación es igualdad de objeto

Esto se ajusta a la comprensión común del boxeo y el desempaquetado, eso solo se hace cuando hay una falta de coincidencia.

Primero explicaré exactamente cuándo == es una igualdad de referencia, y precisamente cuando es una igualdad numérica. Las condiciones para la igualdad de referencia son más simples, por lo que se explicarán primero.

JLS 15.21.3 Operadores de igualdad de referencia == y !=

Si los operandos de un operador de igualdad son de tipo de referencia o nulo , entonces la operación es igualdad de objeto.

Esto explica lo siguiente:

 System.out.println(new Integer(0) == new Integer(0)); // "false" 

Ambos operandos son Integer , que son tipos de referencia, y es por eso que == es una comparación de igualdad de referencia, y dos objetos new nunca serán == uno con el otro, por lo que se imprime como false .

Para == ser igualdad numérica, al menos uno de los operandos debe ser un tipo numérico ; esto se especifica de la siguiente manera:

JLS 15.21.1 Operadores de igualdad numérica == y !=

Si los operandos de un operador de igualdad son ambos de tipo numérico, o uno es de tipo numérico y el otro es convertible a tipo numérico, se realiza una promoción numérica binaria en los operandos. Si el tipo promovido de los operandos es int o long , entonces se realiza una prueba de igualdad de enteros; si el tipo promocionado es float or doble`, entonces se realiza una prueba de igualdad de coma flotante.

Tenga en cuenta que la promoción numérica binaria realiza conversión de conjunto de valores y conversión de unboxing.

Por lo tanto, considere lo siguiente:

 System.out.println(new Integer(0) == 0); // "true" 

Esto se ve true , porque:

  • el operando derecho es un tipo int numérico
  • el operando izquierdo es convertible a un tipo numérico, mediante unboxing a int
  • por lo tanto == es una operación de igualdad numérica

Resumen

  • Si ambos operandos de == y != Son tipos de referencia, siempre será una operación de igualdad de referencia
    • No importa si los operandos son convertibles a tipos numéricos
  • Si al menos uno de los operandos es de tipo numérico, siempre será una operación de igualdad numérica
    • El auto-unboxing en uno (como máximo!) De los operandos se realizará si es necesario

Referencias

  • JLS 4.2. Tipos y valores primitivos
    • “Los tipos numéricos son los tipos integrales y los tipos de coma flotante”.
  • Guía de lenguaje Java / Autoboxing
  • Conversión de unboxing JLS 5.1.8
  • JLS 15.21.1 Operadores de igualdad numérica == y !=
  • JLS 15.21.3 Operadores de igualdad de referencia == y !=
  • JLS 5.6.2 Promoción Numérica Binaria

Preguntas relacionadas

  • Cuando se comparan dos Integers en Java, ¿se produce un desempaquetado automático?
  • ¿Por qué son estos == pero no equals() ?
  • Java: ¿Cuál es la diferencia entre el autoboxing y el casting?