Sobes.tech
Middle

Como substituir corretamente o método equals em Java?

sobes.tech IA

Resposta da IA

// Exemplo de redefinição mínima correta de equals
class MyClass {
    private int id;
    private String name;

    public MyClass(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override // Anotação obrigatória
    public boolean equals(Object o) {
        // 1. Verificação de identidade
        if (this == o) return true;
        // 2. Verificação de null e correspondência de classes
        // Usamos getClass() para uma verificação estrita
        if (o == null || getClass() != o.getClass()) return false;
        // 3. Casting
        MyClass myClass = (MyClass) o;
        // 4. Comparação de campos significativos
        return id == myClass.id &&
               // Usamos Objects.equals para comparar objetos (considera null)
               Objects.equals(name, myClass.name);
    }
}

Regras para uma redefinição correta de equals (de acordo com o contrato de Object.equals):

  • Reflexividade: Para qualquer valor não nulo x, x.equals(x) deve retornar true.
  • Simetria: Para quaisquer valores não nulos x e y, x.equals(y) deve retornar true se e somente se y.equals(x) retornar true.
  • Transitividade: Para x, y, e z não nulos, se x.equals(y) e y.equals(z) são true, então x.equals(z) deve ser true.
  • Consistência: Para x e y não nulos, múltiplas chamadas a x.equals(y) devem retornar de forma consistente true ou false, desde que a informação usada para a comparação não mude.
  • Para qualquer valor não nulo x, x.equals(null) deve retornar false.

Recomenda-se usar Objects.equals(obj1, obj2) para comparar objetos de forma segura, pois ele lida corretamente com null.

Sempre sobrescreva hashCode() ao sobrescrever equals(), em conformidade com o contrato geral de Object.hashCode: se dois objetos são iguais de acordo com equals(Object), seus códigos hash, retornados por hashCode(), devem ser iguais. A condição inversa não é obrigatória. Não cumprir essa regra pode causar um funcionamento incorreto de coleções baseadas em tabelas hash (por exemplo, HashMap, HashSet).

// Exemplo de hashCode correspondente para MyClass
class MyClass {
    private int id;
    private String name;

    // ... construtor e equals como acima ...

    @Override
    public int hashCode() {
        // Uso de Objects.hash para calcular o hash de forma conveniente
        return Objects.hash(id, name);
    }
}

Pode gerar automaticamente os métodos equals e hashCode usando IDEs (IntelliJ IDEA, Eclipse), o que é uma boa prática.

Use instanceof em vez de getClass() apenas se a classe fizer parte de uma hierarquia de herança e você precisar que objetos de superclasse e subclasse sejam considerados iguais se tiverem o mesmo estado. Na maioria dos casos, é preferível usar getClass() para uma verificação estrita.