Acabo de ver un código similar a este:
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.out.println(a == b);
Integer c = 100, d = 100;
System.out.println(c == d);
}
}
Cuando se ejecuta, este bloque de código se imprimirá:
false
true
Entiendo por qué el primero es false
: porque los dos objetos son objetos separados, por lo que ==
compara las referencias. Pero no puedo entender, ¿por qué regresa la segunda declaración true
? ¿Existe alguna extraña regla de autoboxing que se activa cuando el valor de un entero está en un cierto rango? ¿Que está pasando aqui?
java
autoboxing
Joel
fuente
fuente
Respuestas:
La
true
línea está realmente garantizada por la especificación del idioma. De la sección 5.1.7 :La discusión continúa, sugiriendo que aunque su segunda línea de salida está garantizada, la primera no lo está (vea el último párrafo citado a continuación):
fuente
valueOf
método de la clase box (comoInteger.valueOf(int)
). Es interesante que la JLS defina el desempaquetado exacto del azúcar, el uso deintValue()
et al, pero no el desempaquetado del box.Integer
que a través de lapublic
API oficial , es decir, llamandointValue()
. Pero hay otras formas posibles de obtener unaInteger
instancia para unint
valor, por ejemplo, un compilador puede generar código manteniendo y reutilizandoInteger
instancias creadas previamente .Salida:
Sí, la primera salida se produce para comparar la referencia; 'a' y 'b': son dos referencias diferentes. En el punto 1, en realidad se crean dos referencias que son similares a:
La segunda salida se produce porque
JVM
intenta ahorrar memoria, cuandoInteger
cae en un rango (de -128 a 127). En el punto 2 no se crea una nueva referencia de tipo Integer para 'd'. En lugar de crear un nuevo objeto para la variable de referencia de tipo Integer 'd', solo se asignó con el objeto creado anteriormente al que hace referencia 'c'. Todos estos son realizados porJVM
.Estas reglas de ahorro de memoria no son solo para Integer. para el propósito de ahorrar memoria, dos instancias de los siguientes objetos de envoltura (mientras se crean a través del boxing), siempre serán == donde sus valores primitivos son los mismos:
\u007f
(7f es 127 en decimal)fuente
Long
también tiene caché con el mismo rango queInteger
.Los objetos enteros en algún rango (creo que tal vez -128 a 127) se almacenan en caché y se reutilizan. Los enteros fuera de ese rango obtienen un nuevo objeto cada vez.
fuente
java.lang.Integer.IntegerCache.high
property. Es interesante que Long no tenga esa opción.Sí, hay una extraña regla de autoencuadre que se activa cuando los valores están en un cierto rango. Cuando asigna una constante a una variable de objeto, nada en la definición del lenguaje indica que se debe crear un nuevo objeto . Puede reutilizar un objeto existente de la caché.
De hecho, la JVM generalmente almacenará una caché de enteros pequeños para este propósito, así como valores como Boolean.TRUE y Boolean.FALSE.
fuente
Supongo que Java mantiene una caché de pequeños enteros que ya están "en caja" porque son muy comunes y ahorra mucho tiempo reutilizar un objeto existente que crear uno nuevo.
fuente
Ese es un punto interesante. En el libro Effective Java, siempre se sugiere anular los iguales para sus propias clases. Además, para verificar la igualdad de dos instancias de objeto de una clase java, siempre use el método equals.
devoluciones:
fuente
En Java, el boxeo funciona en el rango entre -128 y 127 para un entero. Cuando usa números en este rango, puede compararlo con el operador ==. Para los objetos Integer fuera del rango, debe usar equals.
fuente
La asignación directa de un literal int a una referencia Integer es un ejemplo de auto-boxing, donde el compilador maneja el valor literal del código de conversión de objeto.
Entonces, durante la fase de compilación, el compilador se convierte
Integer a = 1000, b = 1000;
enInteger a = Integer.valueOf(1000), b = Integer.valueOf(1000);
.Entonces, es el
Integer.valueOf()
método el que realmente nos da los objetos enteros, y si miramos el código fuente delInteger.valueOf()
método, podemos ver claramente que el método almacena en caché los objetos enteros en el rango de -128 a 127 (inclusive).Entonces, en lugar de crear y devolver nuevos objetos enteros,
Integer.valueOf()
el método devuelve objetos Integer del internoIntegerCache
si el literal int pasado es mayor que -128 y menor que 127.Java almacena en caché estos objetos enteros porque este rango de enteros se usa mucho en la programación diaria, lo que indirectamente ahorra algo de memoria.
La caché se inicializa en el primer uso cuando la clase se carga en la memoria debido al bloque estático. El rango máximo de la caché puede ser controlado por el
-XX:AutoBoxCacheMax
opción JVM.Este comportamiento de almacenamiento en caché no es aplicable solo para objetos Integer, similar a Integer.
ByteCache, ShortCache, LongCache, CharacterCache
paraByte, Short, Long, Character
respectivamente.Puede leer más en mi artículo Java Integer Cache - Why Integer.valueOf (127) == Integer.valueOf (127) Is True .
fuente
En Java 5, se introdujo una nueva función para guardar la memoria y mejorar el rendimiento para el manejo de objetos de tipo Integer. Los objetos enteros se almacenan en caché internamente y se reutilizan a través de los mismos objetos referenciados.
Esto es aplicable para valores enteros en el rango de –127 a +127 (valor entero máximo).
Este almacenamiento en caché de enteros solo funciona en autoboxing. Los objetos enteros no se almacenarán en caché cuando se generen con el constructor.
Para obtener más detalles, consulte el siguiente enlace:
Caché de enteros en detalle
fuente
Si verificamos el código fuente del
Integer
objeto, encontraremos la fuente delvalueOf
método así:lo que puede explicar por qué los
Integer
objetos, que en el rango de -128 (Integer.low
) a 127 (Integer.high
), son los mismos objetos referenciados durante el autoboxing. Y podemos ver que hay una clase queIntegerCache
se encarga de laInteger
matriz de caché, que es una clase deInteger
clase interna estática privada .Hay otro ejemplo interesante que puede ayudarnos a comprender esta extraña situación:
fuente