Dúvida questão [RESOLVIDO]

12 respostas
evertonsilvagomesjav
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();
				
		}
	 }
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?

12 Respostas

douglas_vidotto

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

evertonsilvagomesjav

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…

mario.fts

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

evertonsilvagomesjav

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…

douglas_vidotto

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);
evertonsilvagomesjav

hum ok vlw.

Metal_Java_Full

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

evertonsilvagomesjav

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);

mario.fts

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

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

Constructs a newly allocated Integer object that represents the specified int value.

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

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
		
	}

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

Metal_Java_Full

Noossaa!!!
Preciso anotar essa!
Mto boa!

vlew :!: :!:

S

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”.

evertonsilvagomesjav

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”.

Mto boa explicação.

Criado 8 de fevereiro de 2010
Ultima resposta 26 de ago. de 2010
Respostas 12
Participantes 5