Sobes.tech
Middle

Чӣ тавр дуруст равшан кардани усули equals дар Java?

sobes.tech AI

Ҷавоб аз AI

// Минимален пример за правилно пренаписване на equals
class MyClass {
    private int id;
    private String name;

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

    @Override // Задължителна анотация
    public boolean equals(Object o) {
        // 1. Проверка за идентичност
        if (this == o) return true;
        // 2. Проверка за null и съвпадение на класовете
        // Използваме getClass() за строга проверка
        if (o == null || getClass() != o.getClass()) return false;
        // 3. Привеждане към тип
        MyClass myClass = (MyClass) o;
        // 4. Сравнение на важните полета
        return id == myClass.id &&
               // Използваме Objects.equals за сравнение на обекти (учита null)
               Objects.equals(name, myClass.name);
    }
}

Правила за правилно пренаписване на equals (съгласно контракт Object.equals):

  • Рефлексивност: За всяка ненулева стойност x, x.equals(x) трябва да връща true.
  • Симетрия: За всяка ненулева стойност x и y, x.equals(y) е true ако и само ако y.equals(x) е true.
  • Транзитивност: За всяка ненулева стойност x, y, и z, ако е x.equals(y) и y.equals(z) true, то x.equals(z) трябва да е true.
  • Консистентност: Многократното извикване на x.equals(y) трябва да дава същия резултат, ако данните за сравнение не са се променили.
  • За всяка ненулева стойност x, x.equals(null) трябва да връща false.

Препоръчва се използването на Objects.equals(obj1, obj2) за безопасно сравнение на обекти, тъй като правилно обработва null.

Винаги пренаписвайте hashCode(), когато пренаписвате equals(), според общия контракт Object.hashCode: ако два обекта са равни според equals(), техните hashCode() трябва да са еднакви. Обратното не е задължително. Неспазването на това правило ще доведе до неправилна работа на колекции, базирани на хеш таблици, като HashMap, HashSet.

// Пример за съответстващ hashCode за MyClass
class MyClass {
    private int id;
    private String name;

    // ... конструктор и equals както по-горе ...

    @Override
    public int hashCode() {
        // Използване на Objects.hash за лесно изчисление на хеш
        return Objects.hash(id, name);
    }
}

Методите equals и hashCode могат да бъдат генерирани автоматично с IDE (IntelliJ IDEA, Eclipse), което е добра практика.

Използвайте instanceof вместо getClass() само ако класът е част от йерархията наследяване и искате обекти от суперклас и подклас да се считат за равни, ако имат същото състояние. В повечето случаи е по-добре да използвате getClass() за строга проверка.