Correta implementação de Object#equals e Object#hashCode e ajuda de IDE's

2 respostas
dreampeppers99

De acordo com a documentação oficial, equals indica que um objeto é igual a outro e ainda define.

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

Bem como hashCode deve retornar um valor hash para dado um objeto e com a seguinte afirmação.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

Entendo que, dado um objeto que possua sua lógica de identidade no hashCode o equals só passa mesmo a verificar se o outro a comparar não é nulo e pertence a mesma classe.
public class Modelo {
  private final String modelo;
  public Modelo(final String modelo){
    this.modelo = modelo;
  }

  public int hashCode(){
    return modelo.hashCode();
  }

  public boolean equals(Object outro){
    valide(outro).comoNaoNulo().comoDaClasse(getClass());
    return hashCode() == outro.hashCode();
  }
}

A interpretação está correta?
Se sim, porque os IDE's tanto o Eclipse quanto o Netbeans implementam os snipets codes para equals e hashCode replicando a lógica do hashCode dentro do equals e vice-versa? Ou estou falando bobeira?

2 Respostas

ViniGodoy

Nem sempre.

O método hashCode diz que dois objetos iguais devem ter hashes iguais. Porém, ele não proíbe objetos diferentes de terem hashes iguais.
Portanto, o hashCode não pode ser usado como substituto de um id (pelo menos, não em todos os casos).

Veja como exemplo a classe String e alguns dos seus hashcodes repetidos:
2464: “N.”, “Ll”, “MM”
110990: “pig”, “peã”, “discóbolo”
3143404: “fixa”, “inflamabilidade”
97793703: “fungo”, “fujão”
103156083: “longo”, “lojão”

De fato, essa é uma implementação pouco eficiente, mas perfeitamente válida, de hashcode:

public int hashCode() { return 10; }

Um bom hashcode terá uma chance muito pequena de se repetir, mas a chance existe.
Um hashcode com força de criptografia ainda terá como requisito fornecer uma mudança grande e imprevisível, mesmo que o valor mude pouco.

By the way. As IDEs implementam o hashcode de acordo com o algorítmo proposto por Joshua Block, no Effetive Java.

A descrição do algorítmo fiz nesse post:

Você, a princípio, nem sequer precisa usar todos os campos para o hashcode.
Num objeto que só tem id, vc poderia usar o próprio id e talvez algum outro campo para os objetos que não receberam id ainda.

E claro, você poderia forçar a condição que você comentou: Colocar a lógica de identidade no hashcode. E aí sua implementação poderia ser a que você propôs.
É só importante entender que essa não é a regra geral.

dreampeppers99

ViniGodoy:
Nem sempre.
É só importante entender que essa não é a regra geral.

Entendido perfeitamente, faz total sentido (agora que você explicou é claro) 8)
Obrigado!

Criado 13 de dezembro de 2011
Ultima resposta 13 de dez. de 2011
Respostas 2
Participantes 2