Der Unterschied zwischen == und .equals()

Kurz und bündig: mit .equals() werden Objekte verglichen, mit == Referenzen und simple Typen wie int und boolean.

Inhaltsverzeichnis

Vergleich von primitiven Datentypen

Primitive oder simple Typen wie int, double, long, float etc. sind keine Objekttypen, sondern Sonderformen von Datentypen in Java. Die primitiven Typen haben keine Eigenschaften oder Methoden sondern representieren nur einen Wert. Da es keine Methoden gibt, gibt es natürlich auch kein equals :).

int x = 500;
int y = 500;
System.out.println(x == y);
// Ausgabe: true

Analog zu int werden auch die andereren simplen Typen mit == verglichen.

Vergleich von Referenzen

Ob es sich bei zwei Variablen um ein und das selbe Objekt, also um die Referenz auf das selbe Objekt handelt, kann ebenfalls mit dem "Doppel-ist-gleich" Operator == ermittelt werden. Man sagt auch zwei Objekte haben die selbe Identität, also == vergleicht die Identität.

Person object1 = new Person("1", "Thomas", "Meier");
Person object2 = new Person("1", "Thomas", "Meier");
Person object3 = object1;

System.out.println(object1 == object2);
// Ausgabe: false
System.out.println(object1 == object3);
// Ausgabe: true

Obwohl object1 und object2 die selbe Person beschreiben, sind es trotzdem 2 unterschiedliche Objekte (new erzeugt immer ein neues Objekt!).

Vergleich mittels .equals()

Java ist eine objektorientierte Sprache. Jedes Objekt kann selbst entscheiden ob es gleich einem anderen ist, deswegen hat jedes Objekt eine equals(Object o) Methode. Wenn man eine Klasse erstellt erbt diese die Funktionalität von equals von der Oberklasse bzw. Object. Diese vergleicht allerdings per default nur auf Identität, was of nicht gewünscht ist. Deshalb muss die equals Methode in vielen Fällen überschrieben werden.

Wichtig: wenn eine Klasse die Methode equals() überschreibt, muss die Methode hashCode() ebenfalls überschrieben werden (was aber kein großes Problem ist, siehe unten).

Hier ein Beispiel wie equals und hashCode implementiert werden können:

@Override
public boolean equals(Object o) {
    if (this == o){
        return true;
    }
    if (!(o instanceof Person)){
        return false;
    }

    Person person = (Person) o;
    return Objects.equals(this.id, person.id)
            && Objects.equals(this.firstName, person.firstName)
            && Objects.equals(this.lastName, person.lastName);
}
  • Zuerst wird per this == o überprüft, ob es sich um die selbe Referenz handelt. Falls ja, sind die Objekte natürlich gleich, es handelt sich ja um das selbe Objekt im Speicher
  • Danach wird mit o instanceof Person überprüft, ob das andere Objekt vom selben Type oder einer Unterklasse ist. Wenn nein, können die Objekte nicht gleich sein.
  • Letztendlich wird noch jedes einzelne Feld des anderen Objekts mit dem eigenen verglichen. Nur wenn alle übereinstimmen, sind die Objekte gleich.

Die Implementierung der hashCode() Funktion ist dank der Utility-Klasse Objects recht einfach:

@Override
public int hashCode() {
    return Objects.hash(id, firstName, lastName);
}

Es ist wichtig, die hashCode() Methode zu überschreiben, da sonst manche Datenstrukturen wie z.B. Maps gar nicht oder nicht korrekt mit der Klasse funktionieren.