TL; DR
Java almacena en caché instancias enteras en caja desde -128
hasta 127
. Dado que está utilizando ==
para comparar referencias de objetos en lugar de valores , solo los objetos almacenados en caché coincidirán. long
Trabaje con valores primitivos sin caja o utilícelos .equals()
para comparar sus Long
objetos.
Versión larga (juego de palabras)
¿Por qué hay un problema al comparar la variable Long con un valor mayor que 127? Si el tipo de datos de la variable anterior es primitivo (largo), el código funciona para todos los valores.
Java almacena en caché instancias de objetos Integer del rango -128 a 127 . Dicho eso:
- Si establece en N variables largas el valor
127
(en caché ), todas las referencias señalarán la misma instancia de objeto. (N variables, 1 instancia)
- Si establece en N variables largas el valor
128
( no almacenado en caché ), tendrá una instancia de objeto apuntada por cada referencia. (N variables, N instancias)
Por eso es que esto:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2);
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4);
Produce esto:
verdadero
falso
Para el valor 127L , dado que ambas referencias (val1 y val2) apuntan a la misma instancia de objeto en la memoria (en caché), devuelve true
.
Por otro lado, para el valor 128 , dado que no hay una instancia almacenada en caché en la memoria, se crea una nueva para cualquier asignación nueva de valores en caja, lo que da como resultado dos instancias diferentes (señaladas por val3 y val4) y regresando false
en el comparación entre ellos.
Eso sucede únicamente porque está comparando dos Long
referencias de objeto , no long
valores primitivos, con el ==
operador. Si no fuera por este mecanismo de caché, estas comparaciones siempre fallarían, por lo que el verdadero problema aquí es comparar los valores en caja con el ==
operador.
Cambiar estas variables a long
tipos primitivos evitará que esto suceda, pero en caso de que necesite mantener su código usando Long
objetos, puede hacer estas comparaciones de manera segura con los siguientes enfoques:
System.out.println(val3.equals(val4)); // true
System.out.println(val3.longValue() == val4.longValue()); // true
System.out.println((long)val3 == (long)val4); // true
(Es necesaria una verificación nula adecuada, incluso para fundiciones)
En mi opinión , siempre es una buena idea seguir con los métodos .equals () cuando se trata de comparaciones de objetos.
Enlaces de referencia:
.longValue()
.La comparación de no primitivos (también conocidos como Objetos) en Java con
==
compara su referencia en lugar de sus valores.Long
es una clase y, por tanto, losLong
valores son Objetos.El problema es que los desarrolladores de Java querían que las personas usaran
Long
como solíanlong
proporcionar compatibilidad, lo que llevó al concepto de autoboxing, que es esencialmente la característica, quelong
-values se cambiará aLong
-Objects y viceversa según sea necesario. Sin embargo, el comportamiento del autoboxing no es exactamente predecible todo el tiempo, ya que no está completamente especificado.Entonces, para estar seguro y tener resultados predecibles, use siempre
.equals()
para comparar objetos y no confíe en el autoboxing en este caso:fuente