public Integer startingI;
public void methodA() {
Integer i = new Integer(25);
this.startingI = i;
System.out.println(this.startingI == i);
methodB(i);
}
private void methodB(Integer i2) {
i2 = i2.intValue();
System.out.println(this.startingI == i2) // nao entendi pq retorna false...sei que é por causa do método intValue mas pq?;
System.out.println(this.startingI.equals(i2));
}
public static void main(String[] args) {
new MyClass().methodA();
}
}
[/code]
Galera pq o teste de == ali retorna false? Eu sei que o metodo intValue() retorna um int e que == analisa a referencia na memoria porém se comparado um Integer com um int se ambos tiverem o mesmo valor retorna true como por exemplo:
Integer a = 125;
int b = 125;
System.out.println(a==b); // retorna true
Então pq o retorno e falso no teste dentro do método?
Acredito que seja por isso… dentro de methodA() você possui duas variáveis referenciando um objeto Integer cujo valor é 25. Essas variáveis são startingI e i. Depois você chama methodB() passando como argumento a variável i. Ao fazer isso, agora você tem 3 variáveis apontando para o objeto Integer cujo valor é 25: startingI, i e i2. Porém, em methodB() você faz o seguinte comando: i2 = i2.intValue();. Nesse ponto acredito que ocorra um boxing do valor retornado por intValue() criando um novo objeto Integer. Assim, startingI e i2 apontam para objetos diferentes na memória, mas que possuem o mesmo valor. Por isso no seu teste de == o valor é falso.
Edit: Para finalizar… no seu outro teste:
Integer a = 125;
int b = 125;
System.out.println(a == b); //imprime true
Isso acontece por que ocorre um unboxing do valor do objeto referenciado por a. Assim temos dois ints sendo comparados. Aí, como o valor é o mesmo, == retorna true
Por um acaso cai neste tópico e notei que há um pequeno equívoco que pode gerar confusão no entendimento de algumas pessoas. Deixarei meu comentário pois pode servir como referência.
Nem SEMPRE que é feito um boxing, o new Integer() é chamado.
Antes de mais nada é realizada uma verificação no cache, para ver se já foi feito algum outro boxing que bata com o mesmo tipo e valor deste, até o limite do valor de 127. Se já existe, NÃO é feito o new Integer().
Neste caso a variável em questão, apenas referencia o mesmo endereço de memória do objeto já existente no cache.
Não se ater a este “detalhe” pode nos confundir pelo seguinte motivo:
Integer a = 25; //novo objeto
Integer b = 25; //usa o mesmo objeto acima. Obs.: se fizéssemos "Integer b = a;" também funcionaria, mas estaríamos simplesmente passando a referência de "a" diretamente. Daí não faria boxing, muito menos usaria o sistema de caching.
b = b.intValue(); //faz unboxing e logo após, boxing novamente. No momento do boxing, é usado o mesmo objeto da variável de referência "a" em cache.
System.out.println(a == b); //true
Resultado: true. Pois a variável “b” apenas apontou para o mesmo objeto armazenado no cache outrora criado pela variável “a”. Então “b” “aponta” para o mesmo objeto no Heap que “a”. Logo podem-se considerar iguais.
enquanto:
Integer a = new Integer(25); //novo objeto.
Integer b = a; // isto é apenas uma cópia da referência "a". Até aqui b == a é verdadeiro.
b = b.intValue(); //ao fazer o boxing, não há cache, logo é criado o novo objeto diferente com "new Integer()".
System.out.println(a == b); //false
Resulta em false. Pois até a linha 3 ainda não tinha sido criado nenhum objeto utilizando a estratégia boxing, logo não existia nada armazenado no cache. Neste caso sim é feito o new Integer() criando um novo endereço de memória. Então após a linha 3, a variável “a” e “b” são objetos diferentes.
No caso do exemplo original o parâmetro que methodB() recebe não foi criado através de boxing. Apenas frisando, como “i” foi criado da forma mais completa (Integer i = new Integer(25)), nada foi armazenado no cache, então ao fazer o boxing na variável “i2”, a classe Integer não encontra nada no cache, então o Construtor (new Integer(25)) é chamado, criando um novo objeto. Por isso o código retorna false.
Apenas como um exemplo, com o simples processo de alterar a linha que cria “Integer i = new Integer(25)” para “Integer i = 25”, já seria o suficiente para o código retornar true, ao invés de false, já que a linha “i2 = i2.intValue()” não faria um new Integer(), mas sim usaria o mesmo endereço de memória que a variável “i” estaria “apontando”.
[quote=stone010]Por um acaso cai neste tópico e notei que há um pequeno equívoco que pode gerar confusão no entendimento de algumas pessoas. Deixarei meu comentário pois pode servir como referência.
Nem SEMPRE que é feito um boxing, o new Integer() é chamado.
Antes de mais nada é realizada uma verificação no cache, para ver se já foi feito algum outro boxing que bata com o mesmo tipo e valor deste, até o limite do valor de 127. Se já existe, NÃO é feito o new Integer().
Neste caso a variável em questão, apenas referencia o mesmo endereço de memória do objeto já existente no cache.
Não se ater a este “detalhe” pode nos confundir pelo seguinte motivo:
Integer a = 25; //novo objeto
Integer b = 25; //usa o mesmo objeto acima. Obs.: se fizéssemos "Integer b = a;" também funcionaria, mas estaríamos simplesmente passando a referência de "a" diretamente. Daí não faria boxing, muito menos usaria o sistema de caching.
b = b.intValue(); //faz unboxing e logo após, boxing novamente. No momento do boxing, é usado o mesmo objeto da variável de referência "a" em cache.
System.out.println(a == b); //true
Resultado: true. Pois a variável “b” apenas apontou para o mesmo objeto armazenado no cache outrora criado pela variável “a”. Então “b” “aponta” para o mesmo objeto no Heap que “a”. Logo podem-se considerar iguais.
enquanto:
Integer a = new Integer(25); //novo objeto.
Integer b = a; // isto é apenas uma cópia da referência "a". Até aqui b == a é verdadeiro.
b = b.intValue(); //ao fazer o boxing, não há cache, logo é criado o novo objeto diferente com "new Integer()".
System.out.println(a == b); //false
Resulta em false. Pois até a linha 3 ainda não tinha sido criado nenhum objeto utilizando a estratégia boxing, logo não existia nada armazenado no cache. Neste caso sim é feito o new Integer() criando um novo endereço de memória. Então a variável “a” e “b” são objetos diferentes.
No caso do exemplo original o parâmetro que methodB() recebe não foi criado através de boxing. Apenas frisando, como “i” foi criado da forma mais completa (Integer i = new Integer(25)), nada foi armazenado no cache, então ao fazer o boxing na variável “i2”, a classe Integer não encontra nada no cache, então o Construtor (new Integer(25)) é chamado, criando um novo objeto. Por isso o código retorna false.
Apenas como um exemplo, com o simples processo de alterar a linha que cria “Integer i = new Integer(25)” para “Integer i = 25”, já seria o suficiente para o código retornar true, ao invés de false, já que a linha “i2 = i2.intValue()” não faria um new Integer(), mas sim usaria o mesmo endereço de memória que a variável “i” estaria “apontando”.[/quote]