Como padrão .equals e .hashCode funcionarão para minhas classes?

106

Diga que eu tenho minha própria aula

public class MyObj { /* ... */ }

Possui alguns atributos e métodos. NÃO implementa igual, NÃO implementa hashCode.

Depois de chamar equals e hashCode, quais são as implementações padrão? Da classe de objeto? E quais são eles? Como o padrão igual funcionará? Como o hashCode padrão funcionará e o que retornará? == irá apenas verificar se eles fazem referência ao mesmo objeto, então é fácil, mas e os métodos equals () e hashCode ()?

alexeypro
fonte

Respostas:

94

Sim, a implementação padrão é Object (em geral; se você herdar de uma classe que redefiniu igual a e / ou hashCode, você usará essa implementação).

Da documentação:

equals

O método equals para a classe Object implementa a relação de equivalência mais discriminatória possível nos objetos; ou seja, para quaisquer valores de referência não nulos x e y, este método retorna verdadeiro se e somente se x e y se referem ao mesmo objeto (x == y tem o valor verdadeiro).

hashCode

Por mais que seja razoavelmente prático, o método hashCode definido pela classe Object retorna inteiros distintos para objetos distintos. (Isso geralmente é implementado convertendo o endereço interno do objeto em um número inteiro, mas essa técnica de implementação não é exigida pela linguagem de programação JavaTM).

Etienne de Martel
fonte
50

Em Objectuma das implementações JVM:

public boolean equals(Object object) {
    return this == object;
}

public int hashCode() {
    return VMMemoryManager.getIdentityHashCode(this);
}

Em ambos os casos, é apenas uma comparação dos endereços de memória dos objetos em questão.

Brad Mace
fonte
7
De qual versão do JDK é? In v6u23 ea:public native int hashCode();
khachik
@kha - Você está certo, acho que rastreei uma das implementações nativas para ver o que realmente fazia
Brad Mace
10

Existem implementações padrão de equals()e hashCode()em Object. Se você não fornecer sua própria implementação, ela será usada. Pois equals(), isso significa uma ==comparação: os objetos só serão iguais se forem exatamente o mesmo objeto. Pois hashCode(), o Javadoc tem uma boa explicação.

Para obter mais informações, consulte Effective Java, Capítulo 3 (pdf), item 8.

Jorn
fonte
1

Sim, da Objectclasse, já que sua classe estende Object implicitamente. equalssimplesmente retorna this == obj. hashCodea implementação é nativa. Apenas um palpite - ele retorna o ponteiro para o objeto.

Khachik
fonte
2
É um ponteiro para o objeto localizado na memória, mas não é um endereço de memória do objeto. O GC pode mover o objeto pela memória e o código hash permanecerá o mesmo.
Jeremy
Obrigado @Jeremy. stackoverflow.com/questions/2427631/… pode ser interessante.
khachik
1

Se você não fornecer sua própria implementação, uma derivada de Object será usada. Está tudo bem, a menos que você planeje colocar suas instâncias de classe em, por exemplo, HashSet (qualquer coleção que realmente use hashCode ()), ou algo que precise verificar a igualdade do objeto (ou seja, o método contains () de HashSet). Caso contrário, funcionará incorretamente, se é isso que você está pedindo.

É muito fácil fornecer sua própria implementação desses métodos graças ao HashCodeBuilder e EqualsBuilder da Apache Commons Lang .

Paweł Dyda
fonte
(a) Por que você diz que a 'implementação padrão de' igual 'da classe Object não funcionará corretamente com o HashSet? Isso contradiz as outras respostas nesta página. (b) Obrigado pelos links Commons Lang.
Basil Bourque
1
@Basil: Não acho que isso se contradiga. É claro que a implementação padrão funcionaria ... de alguma forma, mas não da maneira que você esperava. Ou seja, como equals () usa igualdade de referência, dois objetos idênticos seriam "diferentes" aos olhos da implementação padrão. Como resultado, você pode acabar tendo duas instâncias diferentes da mesma coisa em seu Conjunto. E o uso típico de Conjuntos é quando você deseja eliminar duplicatas ...
Paweł Dyda
@ PawełDyda: O comportamento padrão geralmente é correto para tipos mutáveis. Se Fooe Barsão referências a duas instâncias diferentes de um tipo mutável, e existe um método (por exemplo SomeMutatingMethod) que Foo.SomeMutatingMethod()não afeta Barda mesma forma que afeta Foo, essa diferença deve ser suficiente para considerar os objetos como desiguais.
supercat
0

A developerworks da IBM diz:

Sob esta implementação padrão, duas referências são iguais apenas se se referem ao mesmo objeto exato. Da mesma forma, a implementação padrão de hashCode () fornecida por Object é derivada do mapeamento do endereço de memória do objeto para um valor inteiro.

No entanto, para ter certeza dos detalhes exatos de implementação para a versão Java de um determinado fornecedor, é provavelmente melhor olhar como a fonte (se estiver disponível)

Brabster
fonte