Comparar valores Long no primitivos 127 y 128

Quiero comparar dos valores de objetos largos usando condiciones if . Cuando estos valores son inferiores a 128 , la condición if funciona correctamente, pero cuando son mayores o iguales a 128 , la comparación falla.

Ejemplo:

 Long num1 = 127; Long num2 = 127; if (num1 == num2) { // Works ok } 

La comparación en el código anterior funciona correctamente, pero falla en el siguiente código:

 Long num1 = 128; Long num2 = 128; if (num1 == num2) { // Does NOT work } 

¿Por qué hay un problema al comparar variables largas con valores mayores que 127 ? Si los tipos de datos variables se cambian a primitivos largos , entonces las comparaciones funcionan para todos los casos.

¿Por qué hay un problema al comparar Long variable con un valor mayor a 127? Si el tipo de datos de la variable anterior es primitivo (largo), entonces el código funciona para todos los valores.

Java almacena instancias de objetos enteros del rango -128 a 127 . Eso dijo:

  • Si establece en N variables largas el valor 127 (en caché ), todas las referencias apuntarán a la misma instancia de objeto. (N variables, 1 instancia)
  • Si establece en N variables largas el valor 128 ( no en caché ), tendrá una instancia de objeto apuntada por cada referencia. (N variables, N instancias)

Por eso esto:

 Long val1 = 127L; Long val2 = 127L; System.out.println(val1 == val2); Long val3 = 128L; Long val4 = 128L; System.out.println(val3 == val4); 

Salidas esto:

cierto
falso

Para el valor de 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 ninguna instancia para almacenar en memoria caché, se crea una nueva para cualquier asignación nueva de valores encuadrados, lo que da como resultado dos instancias diferentes (apuntadas por val3 y val4) y devuelve false en la comparación entre ellos.

Eso ocurre únicamente porque está comparando dos referencias de objetos Long , no valores primitivos long , con el operador == . Si no fuera por este mecanismo de caché, estas comparaciones siempre fallarían, por lo que el problema real aquí es comparar valores == con el operador == .

Cambiar estas variables a tipos long primitivos evitará que esto suceda, pero en caso de que necesite mantener su código utilizando objetos Long , 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 

OMI , siempre es una buena idea seguir con los métodos .equals () al tratar con las comparaciones de Objetos.

Descargo de responsabilidad: la mayoría de las comparaciones fallarán si alguno de estos valores es nulo (incluso el lanzamiento a largo arrojará una excepción), por lo que se necesitan verificaciones adicionales para acomodar estos escenarios.

Enlaces de referencia:

num1 y num2 son objetos largos. Debería usar equals() para compararlos. == comparación podría funcionar a veces debido a la forma en que JVM empaqueta las primitivas, pero no depende de ellas.

 if (num1.equals(num1)) { //code } 

Java almacena en caché los valores primitivos de -128 a 127 . Cuando comparamos dos objetos largos java internamente, tipee el valor primitivo y compárelo. Pero por encima de 127, el objeto Long no obtendrá tipo de casta. Java almacena el resultado en caché mediante el método .valueOf () .

Este almacenamiento en caché funciona para Byte, Corto, Largo de -128 a 127. Para el almacenamiento en caché Integer funciona de -128 a java.lang.Integer.IntegerCache.high o 127, el que sea más grande. (Podemos establecer el valor de nivel superior hasta el cual valores enteros debe almacenarse en caché utilizando java.lang.Integer.IntegerCache.high).

  For example: If we set java.lang.Integer.IntegerCache.high=500; then values from -128 to 500 will get cached and Integer a=498; Integer b=499; System.out.println(a==b) Output will be "true". 

Los objetos Float y Double nunca se almacenan en caché.

El personaje obtendrá caché de 0 a 127

Estás comparando dos objetos. entonces == el operador verificará la igualdad de referencias de objetos. Existen las siguientes formas de hacerlo.

1) escriba los dos objetos en valores primitivos y compare

  (long)val3 == (long)val4 

2) leer el valor del objeto y comparar

  val3.longValue() == val4.longValue() 

3) Use el método equals () en la comparación de objetos.

  val3.equals(val4); 

La comparación de elementos no primitivos (también conocidos como objetos) en Java con == compara su referencia en lugar de sus valores. Long es una clase y, por lo tanto, los valores Long son Objects.

El problema es que los Desarrolladores de Java querían que las personas usaran Long como si usaran long para proporcionar compatibilidad, lo que llevó al concepto de autoboxing, que es esencialmente la característica, que long valores long se cambiarán a Long 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.

Para estar seguros y tener resultados predecibles, siempre use .equals() para comparar objetos y no confíe en el autoboxing en este caso:

 Long num1 = 127, num2 = 127; if(num1.equals(num2)) { iWillBeExecutedAlways(); }