2011-12-29 15 views
19

Consideremos primero las siguientes expresiones en Java.El método equals() en Java funciona inesperadamente en el tipo de datos Long

Integer temp = new Integer(1); 
System.out.println(temp.equals(1)); 

if(temp.equals(1)) 
{ 
    System.out.println("The if block executed."); 
} 

Todas estas declaraciones funcionan bien. No hay dudas al respecto. La expresión temp.equals(1) se evalúa a true como se esperaba y la única instrucción dentro del bloque if se ejecuta consecuentemente.


Ahora, cuando cambio el tipo de datos de Integer a Long, la declaración temp1.equals(1) se evalúa de forma inesperada a false de la siguiente manera.

Long temp1 = new Long(1); 
System.out.println(temp1.equals(1)); 

if(temp1.equals(1)) 
{ 
    System.out.println("The if block executed."); 
} 

Estas son las declaraciones equivalentes a las mencionadas en el fragmento anterior sólo el tipo de datos ha cambiado y se comportan exactamente opuesta.

La expresión temp1.equals(1) se evalúa a false y, en consecuencia, la única declaración dentro del bloque if no se ejecuta el que la inversa de los estados anteriores. ¿Cómo?

+0

La documentación dice que '.equals' devuelve verdadero solo si ambos objetos son del tipo' long'. – mc10

+0

Intenté 'if (temp1.longValue() == 1)' y 'if (temp1.equals (1l)' ambos funcionaron como se esperaba. – Lion

Respuesta

31

Estás comparando un Long a un int. El Javadoc para java.lang.Long#equals dice que el método equals

compara este objeto al objeto especificado. El resultado es verdadero si y solo si el argumento no es nulo y es un objeto largo que contiene el mismo valor largo que este objeto.

En lugar de tratar System.out.println(new Long(1).equals(1L)); Ahora que usted está comparando un LongLong a un lugar de una Long a un Integer, se imprimirá true.

+0

¿Funcionaría '1L' también? – TheLQ

+0

@TheLQ ¿Estás preguntando si puedes? do 'new Long (1L)'? Sí, puede. '1L' básicamente representa un tipo' long'. Dado que el constructor 'Long' acepta' long's, aceptará '1L' como el argumento constructor. –

5

El valor literal 1 es no un long, es una int. Pruebe el código anterior con este lugar:

System.out.println(temp1.equals(1L)); 

Y

if (temp1.equals(1L)) 

Como se puede ver, poniendo L después de que el valor literal 1 indica que se trata de un long, y luego las comparaciones funciona como se espera.

0

Puede comparar valores largos/enteros sin utilizar equals(). Esto solo es necesario cuando comparas cadenas de caracteres hasta donde yo sé.

3

Según Javadoc's page on Long, la .equals method evalúa a true sólo si

  1. El argumento es un objeto Long
  2. Si (1) es verdadera, entonces los Long objetos deben tener valores iguales

En su escenario, 1 es un int, no un objeto Long, por lo que falla (1) y therefo re, evalúa a falso. Si necesita realizar una prueba en un long, use 1L en su lugar.

2

Ese comportamiento es consistente con el autoboxing convirtiendo el 1 en un Integer que luego se compara con otro Integer(1). Comparando un Long con un Integer produce false.

Si utilizara 1L para comparar con Long obtendría true.

4

La razón por la que puede hacer esa comparación es por el autoboxing en Java.

El método actual que está llamando es la siguiente:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Long.html#equals(java.lang.Object)

que está comparando su objeto largo a algún otro objeto, no a un int primitivo real.

¿Qué pasa cuando se llama al método es que su primitiva integer(1) está siendo autoboxed en un Object(Integer) es así, que está llamando con eficacia:

new Long(1).equals(new Integer(1)); 

razón por la cual se produce un error.

Por ello, si se llama a

new Long(1).equals(1L) 

esto funcionaría, ya que Java AUTOBOX la 1L (long primitiva, no int) en un objeto Long, no un objeto Integer.

1

La implementación de equals() método de la clase Long ilustra por qué:

public boolean equals(Object obj) { 
    if (obj instanceof Long) { 
     return value == ((Long)obj).longValue(); 
    } 
    return false; 
} 
3

Java está siendo perezoso.

Cuando realiza la siguiente comparación java automáticamente convertirá el int en un largo (como un largo puede contener cualquier valor que pueda contener un int). Y la comparación es entre dos longs y no dos ints.

int i = 1; 
long l = 1L; 
boolean b = i == l; 

Java es capaz de hacer esto porque la información sobre el tipo y il se conoce en tiempo de compilación y al realizar la comparación.Sin embargo, cuando utiliza la versión en caja, el tipo se puede conocer en tiempo de compilación, pero no al realizar la comparación. Esto se debe a que la comparación tiene que hacerse dentro de un método equals, y como equals toma Object como parámetro, la información del tipo se pierde. Por lo tanto, Java es flojo y solo verifica si dos números encuadrados son iguales si ambos son de instancias de la misma clase de Número (por ejemplo, tanto Integer, o Long, o Double, etc ...).

Resulta que la única manera totalmente confiable para comparar dos números de tipo desconocido en tiempo de ejecución es convertir tanto a cadenas y tanto a BigDecimal y después de usar el método compareTo (y no es igual a). Aunque si sabes que solo vas a tener largos y largos, entonces la vida es más simple ya que puedes hacer lo siguiente.

Number n0 = new Long(1L); 
Number n1 = new Integer(1); 
boolean equal = n0.longValue() == n1.longValue(); 
+0

Sería bueno si pudiera agregar un ejemplo y la fuente oficial de la mencionada "forma totalmente confiable" para comparar el valor de dos números de tipo desconocido. ¡Gracias y voto positivo de todos modos! –

2

largo temp1 = new larga (1); System.out.println (temp1.equals (1));

if (temp1.equals (1)) { System.out.println ("El bloque if se ejecutó."); }

en este código temp1.equals(1) está comparando un objeto Long objeto a Integer que da el resultado falsa, podemos corregirlo mediante el uso de 1L en lugar de 1 ,,, por ejemplo temp1.equals(1L), al hacer esto estamos comparando con objeto Long a Long y da resultado VERDADERO

1

El método equals en Java.lang.Long inicialmente comienza con una instancia de verificación larga solo después de que se compara el valor.

public boolean equals(Object obj) { 
    if (obj instanceof Long) { 
     return value == ((Long)obj).longValue(); 
    }   
    return false; 
} 

Así que si usted va a utilizar y el valor entero int el lugar de un valor a largo entonces la primera comprobación falla y por lo tanto usted recibirá falsa como el resultado.

Cuestiones relacionadas