Detalhes sobre comparação de classes Wrapper

5 respostas
rafadelnero

Não ficou muito claro a comparação de classe Wrapper com Integer ou outros Wrappers que não seja String, dois objetos com o mesmo valor comparado com == são considerados diferentes, sendo que a classe e todos seus métodos são final, e também seu código hashcode são os mesmos e na classe String, dois objetos com o mesmo valor são considerados iguais se uma String possuir o mesmo valor de outra e estará apontando para o mesmo objeto por consequência.

Como segue no exemplo:

public static void main(String[] args) {
		Integer teste1 = 300;
		Integer teste2 = 300;
		
		System.out.println(teste1 == teste2); // Saída false
		
		System.out.println(teste1.hashCode()); // Saída 300
		System.out.println(teste2.hashCode()); // Saída 300

                String teste3 = "teste";
		String teste4 = "teste";
		
		System.out.println(teste3 == teste4); // Retorna true
	}

E mais uma dúvida, o operador == compara o código hashcode do objeto mesmo? Ou é outro tipo de código que equivale a referência do objeto?

Valeu!

5 Respostas

kadu.m.lino

O operador == compara a referência do objeto na memória.

.equals() compara o valor

mas pq isso da true?

String teste1 = "teste";  
 String teste2 = "teste"; 
 syso(teste1==teste2)

Porque o java, por questões de performance, cria um pool de String. Quando você cria uma string literal ele procura se há uma string literal nesse pool com o mesmo valor. Caso exista ele aponta para o mesmo lugar.

resumindo:

//isso dá true
"teste" == "teste"


//isso dá false
new String("teste") == new String("teste")
rafadelnero

kadu.m.lino:
O operador == compara a referência do objeto na memória.

.equals() compara o valor

mas pq isso da true?

String teste1 = "teste";  
 String teste2 = "teste"; 
 syso(teste1==teste2)

Porque o java, por questões de performance, cria um pool de String. Quando você cria uma string literal ele procura se há uma string literal nesse pool com o mesmo valor. Caso exista ele aponta para o mesmo lugar.

resumindo:

//isso dá true
"teste" == "teste"


//isso dá false
new String("teste") == new String("teste")

Humm, entendi, mas concluindo, todas as classes Wrapper com exceção da classe String não criam pool de objetos para apontar para o mesmo objetos tendo eles os mesmos valores.
Se criar pool, sei que as classes Integer até o número 127 podem ser comparadas com == que retorna true.

O código que referencia o objeto na memória não pode ser exibido através do Java.

Ruttmann
rafadelnero:
kadu.m.lino:
O operador == compara a referência do objeto na memória.

.equals() compara o valor

mas pq isso da true?

String teste1 = "teste";  
 String teste2 = "teste"; 
 syso(teste1==teste2)

Porque o java, por questões de performance, cria um pool de String. Quando você cria uma string literal ele procura se há uma string literal nesse pool com o mesmo valor. Caso exista ele aponta para o mesmo lugar.

resumindo:
//isso dá true
"teste" == "teste"


//isso dá false
new String("teste") == new String("teste")

Humm, entendi, mas concluindo, todas as classes Wrapper com exceção da classe String não criam pool de objetos para apontar para o mesmo objetos tendo eles os mesmos valores.
Se criar pool, sei que as classes Integer até o número 127 podem ser comparadas com == que retorna true.

O código que referencia o objeto na memória não pode ser exibido através do Java.

Ficou meio confuso o que você escreveu, mas enfim, vou tentar te ajudar.

Pra comparar conteúdo de Wrappers, somente usando o .equals(). Se você usar == ele compara os endereços(referências) de memória de cada uma.

No exemplo abaixo, o resutado será "Diferente":

Integer inteiro1 = new Integer(12);
		Integer inteiro2 = new Integer(12);
		
		if (inteiro1 == inteiro2) {
			System.out.println("Iguais");
		} else {
			System.out.println("Diferentes");
		}

Já nesta, será "Iguais", pois os dois handlers(olha só, palavra nova, que bonita) estão referenciando a um mesmo objeto na memória:

Integer inteiro1 = new Integer(12);
		Integer inteiro2 = inteiro1;
		
		if (inteiro1 == inteiro2) {
			System.out.println("Iguais");
		} else {
			System.out.println("Diferentes");
		}

A única exceção pra isso tudo é a classe String. Entre os Wrappers, String é a classe mais custosa pra se trabalhar e por isso existe o Pool de Strings, por questão de performance.

Só não entendi o que você quis dizer na última frase. Independente do valor informado na instanciação de um Integer, você nunca conseguirá comparar valores usando ==.

Ah, e sobre o Pool de String, tem uma discussão bem interessante aqui.

Rodrigo_Sasaki

Bom, a classe Integer cria um cache dos valores mais utilizados. que via de -128 até 127. Então todos os números nessa faixa podem ser comparados com ==

Explicando melhor. Quando você faz:Integer num = 100;O código que realmente é executado é:Integer num = Integer.valueOf(100);E a implementação do valueOf é a seguinte: public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); } Ou seja, se estiver dentro da faixa, ele retorna o próprio objeto do cache, então a referência será a mesma, e por isso o == funciona.

Repare também que ele vai até um valor IntegerCache.high, que pode ser alterado, através da propriedade java.lang.Integer.IntegerCache.high, ou seja. você pode definir até onde esse cache vai.

Experimente brincar com a propriedade, para ver se tem diferenças no seu teste de igualdade.

E não, o == não compara o resultado do hashCode, porque esse resultado pode ter conflitos, principalmente na classe String. Veja esse código:System.out.println("Aa".hashCode() + "," + "BB".hashCode()); System.out.println("Ba".hashCode() + "," + "CB".hashCode()); System.out.println("Ca".hashCode() + "," + "DB".hashCode()); System.out.println("Da".hashCode() + "," + "EB".hashCode()); Apesar de serem Strings diferentes, elas produzem o mesmo resultado ao invocar hashCode

rafadelnero

Rodrigo Sasaki:
Bom, a classe Integer cria um cache dos valores mais utilizados. que via de -128 até 127. Então todos os números nessa faixa podem ser comparados com ==

Explicando melhor. Quando você faz:Integer num = 100;O código que realmente é executado é:Integer num = Integer.valueOf(100);E a implementação do valueOf é a seguinte: public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); } Ou seja, se estiver dentro da faixa, ele retorna o próprio objeto do cache, então a referência será a mesma, e por isso o == funciona.

Repare também que ele vai até um valor IntegerCache.high, que pode ser alterado, através da propriedade java.lang.Integer.IntegerCache.high, ou seja. você pode definir até onde esse cache vai.

Experimente brincar com a propriedade, para ver se tem diferenças no seu teste de igualdade.

E não, o == não compara o resultado do hashCode, porque esse resultado pode ter conflitos, principalmente na classe String. Veja esse código:System.out.println("Aa".hashCode() + "," + "BB".hashCode()); System.out.println("Ba".hashCode() + "," + "CB".hashCode()); System.out.println("Ca".hashCode() + "," + "DB".hashCode()); System.out.println("Da".hashCode() + "," + "EB".hashCode()); Apesar de serem Strings diferentes, elas produzem o mesmo resultado ao invocar hashCode

Legal Rodrigo Sasaki, a explicação ficou muito boa, valeu!

Criado 6 de setembro de 2013
Ultima resposta 9 de set. de 2013
Respostas 5
Participantes 4