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.
==
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:
==
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
olong
, entonces se realiza una prueba de igualdad de enteros; si el tipo promocionado esfloat 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:
int
numérico int
==
es una operación de igualdad numérica ==
y !=
Son tipos de referencia, siempre será una operación de igualdad de referencia
==
y !=
==
y !=
Integers
en Java, ¿se produce un desempaquetado automático? ==
pero no equals()
?