Wrapper, método equals() e operador ==

5 respostas
rafacyber

Pessoal, bom dia!

Estou estudando para a certificação Java e caí numa dúvida bastante elementar, é o seguinte:

Eu já entendi os conceitos de equals e == com as Strings, mas estou com uma dúvida a respeito dos exemplos da página 141 e 142 do Livro Certificação Sun para Programador Java 6. da Kathy Sierra.

Eis os exemplos:
Exemplo 1:

Integer i1, i2;
        i1 = 10;
        i2 = 10;
        System.out.println((i1==i2)+ " " + (i1.equals(i2))); //Resultado: true, true

Até aí beleza, eu entendo mas quando chego a este exemplo:

Integer i3, i4;
        i3 = 1000;
        i4 = 1000;
        System.out.println((i3==i4)+ " " + (i3.equals(i4))); //O resultado será false, true.

Eis o que a Kathy Sierra explica: Para economizar memória, duas instâncias dos seguintes objetos wrapper serão sempre == quando os seus valores primitivos forem o mesmo:

  • Boolean
  • Byte
  • Character de \u000 até \u007f (7f é 127 em decimal)
  • Short e Integer de -128 até 127

Achei esta explicação bastante confusa, pelo que entendi, para o operador == reconhecer as instâncias com uma classe Wrapper, o valor deve ser incluindo no intervalo entre -128 até 127. O Integer tem um intervalo entre -2^31 e 2^31 - 1. Mas para o operador referenciar para as mesmas intâncias, o Integer deve ter um valor entre -128 até 127.

Exemplo3:

Integer i3, i4;
        i3 = 128;
        i4 = 128;
        System.out.println((i3==i4)+ " " + (i3.equals(i4)));  //resultado: false, true.

Exemplo4:

Integer i3, i4;
        i3 = 127;
        i4 = 127;
        System.out.println((i3==i4)+ " " + (i3.equals(i4)));  //resultado: true, true.

Vocês acham que entendi certo ou estou errado :?:

5 Respostas

E

O operador == serve para verificar se duas referências a objetos são iguais.
O operador equals, quando não sobrecarregado, faz a mesma coisa que o “==”. Quando é feita a sobrecarga, deve comparar os valores dos objetos.
Vou explicar mais ou menos o que o autoboxing faz.

Quando você vê algo como:

Integer i = 1234;

no seu programa Java, o compilador faz na verdade sempre o seguinte:

Integer i = Integer.valueOf (1234);

Como é implementado o “valueOf”? Esse é um método que, dado o valor primitivo, lhe retorna um wrapper correspondente a esse valor primitivo.
Acontece que os wrappers são imutáveis (ou seja, o Integer que contém o valor 1234 não pode ter seu valor alterado por 7890, por exemplo, já que ele não tem um “setter”).
Portanto, você poderia usar apenas uma instância de um objeto Integer e compartilhá-la em todo o programa, se você precisasse apenas do valor (que é o que normalmente você quer fazer).
A implementação da Sun para o Java, nas versões 5 e 6, faz o seguinte: checa se o valor é um valor pequeno (-128 <= x <= 127). Se for pequeno, então Integer.valueOf pode até reaproveitar um Integer que a inicialização da JVM já deixa preparado e pronto. Se o valor for grande, então Integer.valueOf retorna um new Integer() mesmo.
Então, se o Integer for retornado por Integer.valueOf (como é o caso do autoboxing) e ele for suficientemente pequeno, pode ser comparado com outro Integer pequeno retornado por Integer.valueOf usando equals mesmo, já que vai comparar dois objetos que já estavam preparados.
Mas se o Integer tiver sido criado com new Integer, ele é um objeto novo, e com certeza vai ser diferente (usando ==) de qualquer outro objeto que já estava preparado.
No Java 7, essa limitação de -127 <= x <= +128 vai cair; você pode indicar, durante a inicialização da JVM, que intervalo você quer usar (você pode tentar usar um valor maior, para reaproveitar mais elementos, ou menor, para economizar alguns míseros bytes. Fica a gosto do usuário.)

Rafael_Marques1

vc mesmo deu a resposta!

"Para economizar memória, duas instâncias dos seguintes objetos wrapper serão sempre == quando os seus valores primitivos forem o mesmo:

  • Boolean
  • Byte
  • Character de \u000 até \u007f (7f é 127 em decimal)
  • Short e Integer de -128 até 127 "

ou seja, se dois Integer tiverem o mesmo valor, e este valor estiver entre -128 e 127, eles serao considerados iguais.

logo, se os dois forem 127, sao iguais
se for > que 127, só serao iguais caso apontem para o mesmo objeto, e nao caso possuam o mesmo valor

E

Eu não li o livro da Kathy nesse ponto. Mas você deve tomar um pouco de cuidado:

Integer i = 127;
Integer j = new Integer (127);
Integer k = Integer.valueOf (127);
System.out.println ( (i == j) + ", "  +(i == k)); // imprime false, true
System.out.println ( (i.equals (j)) + ", " + (i.equals (k))); // imprime true, true

O objeto referenciado pela variável j é um novo objeto (criado por new), e não é igual (usando ==) a nenhum outro objeto. Cuidado: não é só o valor que importa, mas como o objeto wrapper foi criado.

M

As classes wrappers consideram dois objetos iguais (que retornam true se comparados com equals) quando esses objetos tem os mesmos valores primitivos.

Acontece que quando usando o operador == eles só vão ser iguais para números inteiros se representarem o mesmo valor no cache que o Java cria. No caso da classe Integer, esse cache fica na classe Integer.IntegerCache e vai de low (que vale sempre -128 ) até high (que por padrão vai até 127, mas pode ser configurado via argumento para a JVM pela opção -XX:AutoBoxCacheMax= ).

O pessoal mais experiente pode explicar melhor.

rafacyber

Obrigado pessoal, vocês foram bastantes :smiley: esclarecedores.

Criado 30 de janeiro de 2010
Ultima resposta 30 de jan. de 2010
Respostas 5
Participantes 4