[Resolvido]Wrapper, verificar igualdade

Estou com dúvidas com relação aos Wrappers, analisem meu code:

public class Wrapper {
    public static void main(String[] args) {
		Integer d = 10;
		Integer d1 = new Integer(10);
		Integer d2 = 10;

		System.out.println(d == d1);
		System.out.println(d == d2);
    }
}

Por que isso retorna:

false
true

Não consegui entender o pq disso, posso utilizar um objeto(wrapper) sem nunca instanciar o mesmo?

Me parece que o == não compara o valor e sim a instancia.

Quando vc faz new Integer(10) vc cria um outro objeto integer (uma outra instancia), enquanto na linha d2 = 10 vc tem um outro inteiro com o mesmo valor de d, então eles vão apontar para a mesma instancia.

Eu acho q é isso!

Deveria comprar a referência que a variável aponta…só que se usar um valor fora do intervalo -127 e 128, a comparação falha…no livro dizia que isso era pra economizar espaço…não entendi muito bem.

Qual comparação falha?

Quer dizer que o compilador do Java identifica que, se houver um valor dentro desse intervalo de -127 até 128 ele usa a mesma referência de memória para as variáveis o que faz com que a comparação por == funcione corretamente. Caso contrário, a comparação falha.

Quando você usa o operador new está obrigando o compilador do Java a criar uma nova referência para aquela variável mesmo que esteja no intervalo de -127 a 128 como descrito.

Veja o código abaixo:

public class Wrapper{

public static void main(String args[]){

        Integer d1 = 500;
        Integer d2 = new Integer(500);
        Integer d3 = 500;

        System.out.println("Integers: ");
        System.out.println( d1 ==  d2 );
        System.out.println( d1 ==  d3 );
        System.out.println( d1.equals( d2 ) );
        System.out.println( d1.equals( d3 ) );
}
}

A saída é false para a primeira comparação , a segunda comparação falha e retorna falso, true para a terceira comparação e true para a quarta comparação.

Não é que a verificação falha quando os valores não estão no intervalo citado ( -128 e 127 ), simplesmente retorna false por que não são a mesma referência na memória.

Acontece que os objetos que representam os valores entre -128 e 127 são guardados em um cache. Quando um destes valores é atribuído a uma variável, ele vem deste cache, portanto a mesma referência será atribuída as variáveis. Porém se o valor estiver fora desta faixa, um novo objeto será criado a cada declaração, por isso a comparação com == retorna false.

Entendi. Outra coisa, um wrapper então pode armazenar tanto um tipo primitivo quanto um objeto, se eu atribuir um tipo primitivo assim:

Integer i = 10;

Posso tratar a variável i como se fosse um objeto? Ficou meio confuso essa “mistura” de primitivos e objetos.

[quote=gRoOve]Entendi. Outra coisa, um wrapper então pode armazenar tanto um tipo primitivo quanto um objeto, se eu atribuir um tipo primitivo assim:

Integer i = 10;

O wrapper é um objeto que guarda um valor primitivo.

E o que permite que se passe um valor primitivo diretamente para seu respectivo wrapper é o auto-boxing. A grosso modo, o auto-boxing “converte” o valor primitivo para um objeto wrapper no momento da atribuição, por isso a atribuição é válida. O mesmo vale para o processo inverso.

http://www.guj.com.br/java/145082-duvida-basica-autoboxing-mais-cast-resolvido#781999

Sua variável “i” é do tipo Integer, por isso pode usá-la para chamar os métodos normalmente. Só não seria possível se fosse do tipo int.

Finalmente entendi o conceito do auto-boxing. Na verdade ele não converte então, o primitivo está lá, o wrapper só permite que eu lide com ele de forma que fosse um objeto, seria isso?

O Wrapper realmente guarda o valor primitivo, mas de alguma forma eu tenho que recuperar este valor, além disso, para “converter” o primitivo em objeto, o objeto deve ser criado, concorda? Para isso existem métodos específicos, e o trabalho do auto-boxing é chamar estes métodos implicitamente, assim o programador escreve menos código.

Por exemplo, para obter um objeto Integer a partir de um int explicitamente, deveríamos fazer assim:

Integer i = Integer.valueOf(10); // Este método retorna um objeto do tipo Integer que representa o valor 10

O compilador permite que a atribuição seja feita diretamente, neste caso, ocorre o auto-boxing:

[code]Integer i = 10; // Escrevi este código no meu programa

. . .
Integer i = Integer.valueOf(10); // Mas este é o código que será executado implicitamente[/code]
O processo de auto-unboxing ocorre de forma parecida:

[code]Integer wrapper = 10; // Tenho uma variável com a referência de um Wrapper

int primitive = wrapper; // Escrevi este código no meu programa

. . .
int primitive = wrapper.intValue(); // Mas este é o código que será executado implicitamente[/code]

Algo que acho estranho ainda, é que é possível criar o objeto wrapper sem o uso do “new”, aqui por exemplo. Ou o new foi encapsulado no método valueOf ?

Integer i = Integer.valueOf(10); // Este método retorna um objeto do tipo Integer que representa o valor 10 

Outra dúvida, mas não tem a ver com o tópico…fui tentar copiar o código que vc postou usando a função “copy to clipboard”, o sistema retonar que foi copiado. Agora como faço pra colar na menssagem?

[quote=gRoOve]Algo que acho estranho ainda, é que é possível criar o objeto wrapper sem o uso do “new”, aqui por exemplo. Ou o new foi encapsulado no método valueOf?

Integer i = Integer.valueOf(10); // Este método retorna um objeto do tipo Integer que representa o valor 10

O new foi encapsulado. O valueOf é um método estático da classe Integer que retorna a referência do cache, caso o valor esteja entre -128 e 127, e caso o valor esteja além desta faixa, retorna um “new Integer(valor)”. Se fosse usado new Integer diretamente, os valores do cache nunca seriam aproveitados.

Eu nunca usei este “copy to cliboard”, mas se foi para o clipboard é só colar com Ctrl + V ou com o botão direito do mouse. Para isso eu clico em “view plain”, seleciono a parte que eu quero e copio o código.

Obrigado Eric, acho que agora sanei minhas dúvidas sobre Wrapper.