Metoda equals() i hashCode()

Metoda equals (dziedziczona z klasy object) służy do porównywania obiektów(zwraca wartość true lub false), jako argument przyjmuje obiekt klasy object (czyli w praktyce dowolny obiekt).
W podstawowej implementacji sprawdzana jest wyłącznie równość referencji (czy zmienne wskazują na ten sam obszar w pamięci). Jest to zachowanie analogiczne do użycia operatora ==.

class Samochod {
    String marka;
    String model;
    public Samochod(String ma, String mo) {
        marka = ma;
        model = mo;
    }
}

public class FabrykaSamochodow {
    public static void main(String[] args) {
        Samochod samochod1 = new Samochod("Opel", "Corsa");
        Samochod samochod2 = new Samochod("Opel", "Corsa");
        System.out.println("samochod1 == samochod2:");
        System.out.println(samochod1 == samochod2);
        System.out.println("samochod1.equals(samochod2):");
        System.out.println(samochod1.equals(samochod2));
    }
}


Wynikiem będzie dwa razy false ponieważ zmienne referencyjne wskazują na dwa różne obiekty w pamięci.

public class FabrykaSamochodow {
    public static void main(String[] args) {
        Samochod samochod1 = new Samochod("Opel", "Corsa");
        Samochod samochod2 = samochod1;
        System.out.println("samochod1 == samochod2:");
        System.out.println(samochod1 == samochod2);
        System.out.println("samochod1.equals(samochod2):");
        System.out.println(samochod1.equals(samochod2));
    }
}


W tym wypadku wynikami porównań będzie dwa razy true, ponieważ zmienna samochod1 jak i samochod2 wskazują na ten sam obiekt(ten sam obszar w pamięci).

Przesłanianie metody equals()
Dobrą praktyką jest przesłanianie metody equals i pisanie implementacji według pewnych wytycznych:

  1. Sprawdzanie równości fizycznej np. za pomocą operatora ==, jeśli zwróci true to oznacza że obiekty są sobie równe.
  2. Sprawdzenie czy obiekt przekazany jako argument nie jest null’em.
  3. Sprawdzenie czy obiekt przekazany jako parametr jest tego samego typu.
  4. Rzutowanie na odpowiedni typ.
  5. Sprawdzanie równości poszczególnych pól obiektu.

 

public class Samochod {
    String marka;
    String model;

    public Samochod(String ma, String mo) {
        marka = ma;
        model = mo;
    }
 
    @Override
    public boolean equals(Object obj) {
        // 1
        if (this == obj)
            return true;
        // 2
        if (obj == null)
            return false;
  
        // 3
        if (!(obj instanceof Samochod))
            return false;
        //4
        Samochod s = (Samochod) obj;
          
        // 5
        if(this.marka == s.marka && this.model == s.model)
            return true;
        if(this.marka != null) {
            if(!this.marka.equals(s.marka))
                return false;
        } else if(this.marka == null && s.marka != null)
            return false;
        if (this.model != null) {
            if(!this.model.equals(s.model))
                return false;
        } else if(this.model == null && s.model != null)
            return false;
        return true;
    }
}

hashCode()

Metoda hashCode() zwraca prymitywny int który jest swego rodzaju identyfikatorem i powinien być zawsze taki sam dla danego obiektu.

Kontrakt pomiędzy equals() a hashCode()

Kontrakt ten mówi, że jeżeli wartości hashCode dwóch obiektów są identyczne, to obiekty te mogą być równoznaczne. Jeśli jednak hashe są inne, to metoda equals() zawsze zwróci false.

Implementacja equals() i hashCode()

Ręczne pisanie implementacji jest czynnością monotonną i zwykle nie ma sensu robić tego samemu. Polecam do tego celu wykorzystać swoje IDE które zrobi to za nas.

 

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *