Dúvida questão [RESOLVIDO]

[code]package com.certificação.oo1;

public class MyClass {

	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

Não sabia que ele iria criar um novo objeto ali não…

E criado entao um novo objeto integer? Pq na realidade ele ta fazendo um unboxing de Integer pra int…

Na realidade vc ta fazendo de Integer pra int e pra Integer de novo, pq a variável i2 é do tipo Integer.

hum é isso mesmo, unboxing de Integer pra int e boxing de int pra Integer de novo, mas nao entendo pq ele cria um novo objeto…

Ele cria um novo objeto porque toda vez que ele faz um boxing, ocorre um processo parecido com isso (pelo que está no livro da Kathy Sierra):

//Quando fazemos  i2 = i2.intValue(); ocorre algo parecido com isso
int x = i2.intValue();
i2 = new Integer(x);

hum ok vlw.

Dizer que um objeto (startingI) não pode ser comparado com uma variável primitiva (i2 = i2.intValue()) com == , faz algum sentido??

Nao faz pq vc pode comparar com == que da true, a questao e que realmente ele criou um novo objeto.

Se vc fizer um teste vera que da true:

Integer a = new Integer(10) int b = 10; System.out.println(a == b);

se no unboxing ele usar new Integer(10), ele vai criar um novo:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Integer.html#Integer(int)

Vc tem que considerar tbm o fator de cache do integer.

[code] public static void main(String[] args) {

	Integer a = 127;
	Integer b = 127;
	
	System.out.println(a==b); //imprime true
	
	Integer c = 128;
	Integer d = 128;
	
	System.out.println(c==d); // imprime false
	
}[/code]

PQ? pq o Integer tem um cache interno de objetos, até o 127. Os objetos maiores que 127 são criados dinamicamente.

Noossaa!!!
Preciso anotar essa!
Mto boa!

vlew :!: :!:

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]

Mto boa explicação.