2009-07-18 9 views
8

consideran este código:comportamiento incoherente sobre los == de java

class test { 
    public static void main(String[] args) { 
     test inst_test = new test(); 
     int i1 = 2000; 
     int i2 = 2000; 
     int i3 = 2; 
     int i4 = 2; 
     Integer Ithree = new Integer(2); // 1 
     Integer Ifour = new Integer(2); // 2 
     System.out.println(Ithree == Ifour); 
     inst_test.method(i3 , i4); 
     inst_test.method(i1 , i2); 
    } 
    public void method(Integer i , Integer eye) { 
     System.out.println(i == eye); 
    } 
} 

Imprime:

false 
true 
false 

entiendo la primera false, el operador == sólo comprueba si dos referencias están trabajando en el mismo objeto, que en este caso no lo son.

Los siguientes true y false me hacen rascar la cabeza. ¿Por qué Java consideraría i3 y i4 igual pero i1 y i2 diferente? Ambos han sido envueltos en Integer, ¿no deberían ambos evaluar como falsa? ¿Hay alguna razón práctica para esta inconsistencia?

+2

Creo que FindBugs le dirá su error. –

Respuesta

15

Autoboxing de primitivas en objetos (tal como se utiliza en sus llamadas a method utiliza una caché de valores pequeños Desde el Java Language Specification section 5.1.7:. Falsa, un byte

Si el valor p de ser en caja es cierto, , una Char en el rango \ u0000 a \ u007f, o un int o número corto entre -128 y 127, y luego dejar R1 y R2 sea el resultado de cualquiera de los dos conversiones de boxeo de p. siempre es el caso de que R1 == r2.

La parte de discusión de la especificación que sigue inmediatamente también es interesante. Cabe destacar que una JVM puede almacenar en caché más valores si se quiere - no se puede estar seguro de los resultados de hacer:

Integer i1 = 129; 
Integer i2 = 129; 
boolean b = (i1 == i2); 
+0

Esa es una lógica bastante perversa, supongo que se hace por motivos de rendimiento. –

+0

¿Esto realmente tiene un beneficio? Creo que es una decisión de diseño ofuscante. – andandandand

+0

6u14 (y varias variantes p anteriores) tiene una opción para aumentar el rango interno. Es importante para ciertos puntos de referencia y estilos de programación. –

2

Esto se debe a que el boxeo hace que los enteros por debajo de un cierto valor (128, creo) se refieran a algún objeto preconstruido, y valores más altos a objetos nuevos.

7

Cuando se realiza el autoboxing, los enteros entre -128 y 127 se almacenan en caché y se devuelve el mismo objeto contenedor. Lo mismo con valores booleanos y valores char entre \ u0000 y \ u007F

Esto es lo que obtiene la mayor parte del tiempo, sin embargo, depende de la implementación de JVM.

+3

Solía ​​pensar que también dependía de JVM, pero en realidad está en la especificación. –

+2

(O más bien, está especificado para esos valores, pero no para otros.) –

0

Supongo que la envoltura intenta minimizar el número de objetos enteros y crea solo un objeto que representa 2 también para guardar la memoria.

Recuerde no utilizar nunca == en objetos que nunca se sabe lo que sucede.

+0

sí, como han dicho varios, no use == a menos que se busquen efectos específicos respaldados por "sabe lo que sucede" y en uso general: Boolean booLean = Boolean.valueOf (i.intValue() == eye.intValue()); System.out.println (booLean.toString()); –

0

clase Entero contiene un caché de algunos casos de uso frecuente. El rango de valores varía generalmente de JVM para JVM (a veces también es configurable), pero en general el código en cuestión es algo así como:

public static Integer valueOf(int i) { 
    if(i >= -128 && i <= IntegerCache.high) 
     return IntegerCache.cache[i + 128]; 
    else 
     return new Integer(i); 
} 

(código de Sun JDK 1.6)

esto es como cadena de internar, ya que ahorra memoria y permite la prueba de igualdad usando una referencia (ej.== en lugar de es igual)

1

Autoboxing utiliza Integer.valueOf (i), no new Integer (i), para construir un objeto de clase Integer.

Como han dicho los otros, valueOf() usa un caché, principalmente para la eficiencia del espacio.

No use == en los tipos de referencia, casi siempre es un error.

0

Autoboxing utiliza algún mecanismo de caché. Por lo general, nunca debe confiar en ==, siempre use equals para verificar la igualdad.

Cuestiones relacionadas