Acabei de ver um código semelhante 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);
}
}
Quando executado, este bloco de código imprimirá:
false
true
Eu entendo porque o primeiro é false
: porque os dois objetos são objetos separados, então o ==
compara as referências. Mas não consigo descobrir, por que a segunda declaração está retornando true
? Existe alguma regra de autoboxing estranha que entra em ação quando o valor de um inteiro está em um determinado intervalo? O que está acontecendo aqui?
java
autoboxing
Joel
fonte
fonte
Respostas:
A
true
linha é realmente garantida pela especificação do idioma. Da seção 5.1.7 :A discussão continua, sugerindo que, embora sua segunda linha de saída seja garantida, a primeira não é (veja o último parágrafo citado abaixo):
fonte
valueOf
método da classe box (comoInteger.valueOf(int)
). Interessante que o JLS define o desugaring de unboxing exato - usandointValue()
et al - mas não o desugaring de boxing.Integer
senão através dapublic
API oficial , ou seja, chamandointValue()
. Mas existem outras maneiras possíveis de obter umaInteger
instância para umint
valor, por exemplo, um compilador pode gerar manutenção de código e reutilizarInteger
instâncias criadas anteriormente .Resultado:
Sim, a primeira saída é produzida para comparação de referência; 'a' e 'b' - são duas referências diferentes. No ponto 1, na verdade, duas referências são criadas que é semelhante a -
A segunda saída é produzida porque
JVM
tenta economizar memória, quandoInteger
cai em uma faixa (de -128 a 127). No ponto 2, nenhuma nova referência do tipo Inteiro é criada para 'd'. Em vez de criar um novo objeto para a variável de referência do tipo Integer 'd', ele apenas é atribuído ao objeto criado anteriormente referenciado por 'c'. Tudo isso é feito porJVM
.Essas regras de economia de memória não são apenas para números inteiros. para fins de economia de memória, duas instâncias dos seguintes objetos de invólucro (enquanto criados por meio de boxing), serão sempre == onde seus valores primitivos são os mesmos -
\u007f
(7f é 127 em decimal)fonte
Long
também tem cache com o mesmo alcanceInteger
.Objetos inteiros em algum intervalo (acho que talvez -128 a 127) são armazenados em cache e reutilizados. Inteiros fora desse intervalo obtêm um novo objeto a cada vez.
fonte
java.lang.Integer.IntegerCache.high
property. Interessante que Long não tem essa opção.Sim, existe uma estranha regra de autoboxing que entra em ação quando os valores estão em um determinado intervalo. Quando você atribui uma constante a uma variável Object, nada na definição da linguagem diz que um novo objeto deve ser criado. Ele pode reutilizar um objeto existente do cache.
Na verdade, a JVM geralmente armazena um cache de pequenos inteiros para esse propósito, bem como valores como Boolean.TRUE e Boolean.FALSE.
fonte
Meu palpite é que Java mantém um cache de pequenos inteiros que já estão 'encaixotados' porque são muito comuns e economiza muito tempo reutilizar um objeto existente do que criar um novo.
fonte
Esse é um ponto interessante. No livro Effective Java sugere sempre substituir equals para suas próprias classes. Além disso, para verificar a igualdade de duas instâncias de objeto de uma classe java, sempre use o método equals.
retorna:
fonte
Em Java, o boxe funciona no intervalo entre -128 e 127 para um inteiro. Quando estiver usando números neste intervalo, você pode compará-los com o operador ==. Para objetos inteiros fora do intervalo, você deve usar iguais.
fonte
A atribuição direta de um literal int para uma referência Integer é um exemplo de boxing automático, em que o valor literal para o código de conversão de objeto é tratado pelo compilador.
Portanto, durante a fase de compilação, o compilador converte
Integer a = 1000, b = 1000;
paraInteger a = Integer.valueOf(1000), b = Integer.valueOf(1000);
.Portanto, é o
Integer.valueOf()
método que realmente nos dá os objetos inteiros, e se olharmos o código-fonte doInteger.valueOf()
método, podemos ver claramente que o método armazena em cache os objetos inteiros na faixa de -128 a 127 (inclusive).Portanto, em vez de criar e retornar novos objetos inteiros,
Integer.valueOf()
o método retorna objetos inteiros do internoIntegerCache
se o literal int passado for maior que -128 e menor que 127.Java armazena em cache esses objetos inteiros porque esse intervalo de inteiros é muito usado na programação do dia a dia, o que indiretamente economiza alguma memória.
O cache é inicializado no primeiro uso quando a classe é carregada na memória por causa do bloco estático. O intervalo máximo do cache pode ser controlado pela
-XX:AutoBoxCacheMax
opção JVM.Este comportamento de armazenamento em cache não é aplicável apenas a objetos Integer, semelhante a Integer.IntegerCache que também temos
ByteCache, ShortCache, LongCache, CharacterCache
paraByte, Short, Long, Character
respectivamente.Você pode ler mais em meu artigo Java Integer Cache - Why Integer.valueOf (127) == Integer.valueOf (127) Is True .
fonte
No Java 5, um novo recurso foi introduzido para economizar memória e melhorar o desempenho para manipulações de objetos do tipo Inteiro. Objetos inteiros são armazenados em cache internamente e reutilizados por meio dos mesmos objetos referenciados.
Isso é aplicável para valores inteiros no intervalo entre –127 a +127 (valor inteiro máximo).
Este cache inteiro funciona apenas em autoboxing. Objetos inteiros não serão armazenados em cache quando forem construídos usando o construtor.
Para obter mais detalhes, acesse o link abaixo:
Cache Inteiro em Detalhe
fonte
Se verificarmos o código-fonte do
Integer
objeto, encontraremos a fonte dovalueOf
método assim:o que pode explicar por que os
Integer
objetos, que estão no intervalo de -128 (Integer.low
) a 127 (Integer.high
), são os mesmos objetos referenciados durante o autoboxing. E podemos ver que há uma classe queIntegerCache
cuida doInteger
array de cache, que é uma classe interna estática privada deInteger
classe.Há outro exemplo interessante que pode nos ajudar a entender essa situação estranha:
fonte