Objekt1.equals(Objekt2) = immer false. Wieso?

cookiedough

Mitglied
Guten Abend,

zur Zeit habe ich Schwierigkeiten Objekt1.equals(Objekt2) zu verstehen. Ich möchte die zwei Objekte miteinander vergleichen und wenn diese identisch sind sollte true ausgeben.

Java:
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {

        Rechteck einsRechteck = new Rechteck(22, 23);
        Rechteck zweiRechteck = new Rechteck(22, 23);
        System.out.println("Identische Rechtecke? " + einsRechteck.equals(zweiRechteck));
    }
}

Java:
public class Rechteck {
    
     int laenge;
     int breite;

    public Rechteck(int laenge, int breite) {
        this.laenge = laenge;
        this.breite = breite;
    }
}
 
Da hast du ein VerständnisProblem. Das ist nur True wenn es wirklich die gleichen Objekte sind, nicht wenn sie den gleichen Inhalt haben
 
Ich verstehe, was müsste ich machen um die Inhalte der Objekte zu vergleichen.
Ich habs auch mit Arrays.equals(Objekt1, Objekt2) versucht. Dafür erhalte ich einen Fehler.
 
Solange equals nicht überschrieben wurde, muss es genau das selbe Objekt sein.

Wenn die Objekte auch gleich sind, wenn sie nicht das selbe Obekt sind, musst du equals sinnvoll überschreiben, das fehlt bei dir 🙂
 
OK,

bedeutet, dass ich mich an ein englischsprachiges Forum wenden muss, weil ich dort (im Gegensatz zu hier) "richtige" Hilfe bekomme.

Wie von anderen bereits bemerkt:
 
Wenn du einfach nur fertigen Code vorgelegt bekommen möchtest, ohne selbst was zu tun: Ja, dann bist du hier falsch aufgehoben.

Wenn du dir beim Suchen irgendeines Kritikpunktes an dem Forum hier mehr mühe gibst, als bei den von dir eröffneten Threads: Ja, auch dann bist du hier falsch. (Ich meint, du hast ersthaft einen 14 Jahre(!) alten Thread rausgesucht, in dem eine Person sich beschwert hat. Kaum jemand der damals aktiven ist jetzt noch hier aktiv.)


Falls du aber sehr kompetente Hilfe bei quasi allem, was direkt mit Java zu tun hat, erhalten möchtest, um solche Probleme dann auch selbst lösen zu könne: Dann bist du hier richtig.
 
OK,

bedeutet, dass ich mich an ein englischsprachiges Forum wenden muss, weil ich dort (im Gegensatz zu hier) "richtige" Hilfe bekomme.

Wie von anderen bereits bemerkt:
Du hast sehr wohl richtige Antworten erhalten...Du musst nur etwas deinen Kopf angstrengen und nicht denken dass dir jeder alles vorkaut...

Wenn du deine Objekte auf Gleichheit prüfen willst, dann muss in dieser Klasse eine Methode dazu geschrieben werden. Stichwort Comparable oder du überschreibst wie schon gesagt die .equals() Methode.
 
Wenn du deine Objekte auf Gleichheit prüfen willst, dann muss in dieser Klasse eine Methode dazu geschrieben werden. Stichwort Comparable oder du überschreibst wie schon gesagt die .equals() Methode.
Comparable ist da aber ein schlechtes Stichwort, das ist etwas völlig anderes als nur "Gleichheit" und auch in diesem Fall mehr als schlecht geeignet 😉
 
Generell wird es im richtigen Leben auch verdammt selten vorkommen das man den kompletten Inhalt eines komplexen Objekts auf Gleichheit überprüfen muss. Mir ist das bis jetzt jedenfalls noch nie vorgekommen
 
OK,

bedeutet, dass ich mich an ein englischsprachiges Forum wenden muss, weil ich dort (im Gegensatz zu hier) "richtige" Hilfe bekomme.

Wie von anderen bereits bemerkt:
Hmm ... Geh doch zu StackOverflow. Das ist für Entwickler mit die Quelle für Unterstützung...

Nur eben fürchte ich, dass Du da auch nicht glücklich werden wirst, denn erst einmal wirst Du viele Kommentare erhalten a.la.
- die Frage wurde schon öfters behandelt
Bei Dir vielleicht nicht so aber bei vielen Fragen, die hier einfach beantwortet werden:
- Die Frage ist einfach nicht präzise genug gestellt
- Es wird nach einer Meinung gefragt (a.la. "ist xyz gut?" oder "ist abc besser als def?"

Als Konsequenz hast Du sofort Downvotes auf Deiner Frage und der Thread ist schneller gesperrt als sich vielleicht doch noch jemand der Frage annehmen kann ...

Und um es einmal ganz konkret zu sagen:
Wieso sollte einer von uns sich die Mühe machen, irgend etwas zu erläutern, wenn der Fragesteller ganz offensichtlich selbst sich nicht einmal etwas Zeit nimmt um die Lösung zu finden? Sorry, aber geht es noch?

Hast Du einmal versucht, etwas auf Google zu suchen?
Machen wir mal Hilfe zu Selbsthilfe:
- Es geht ganz offensichtlich um Java
- Du hast da schon erkannt: irgendwas mit (Object.)equals ...
- Du willst eine Einführung auf Deutsch ...

==> Dann such mal bei Google nach: Java equals Einführung

"Ungefähr 148.000.000 Ergebnisse" klingt dann erschreckend ... aber die ersten zwei Treffer sind schon gut ... danach sehe ich gleich eine Reihe YouTube Videos die wohl erläutern ... und danach geht es mit zig Treffern weiter ...

Aber damit bin ich wieder raus aus dem Thread. Da gibt es ja nichts, was wirklich diskutiert werden könnte, somit ist mehr als meine Meinung dazu kund zu tun auch nicht notwendig ...
 
Ich habe die Lösung.
Funktioniert in diesem Fall, ohne hashcode() zu überschreiben. Zufall oder geht das immer ohne den hashcode() zu überschreiben?


Java:
public class Rechteck {
   
    //Fehlender Code siehe Beitrag oben
   
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Rechteck rechteck = (Rechteck) o;
        return Double.compare(rechteck.laenge, laenge) == 0 &&
                Double.compare(rechteck.breite, breite) == 0;
    }
}



Dann such mal bei Google nach: Java equals Einführung
Ich kenne die Unterscheidung zwischen ==, equals, Arrays.equals(), Arrays.deepEquals()
Wo erfahre ich als Anfänger weitere weiteren Dutzend Vergleichsmöglichkeiten in Java verwendet werden können.
Außerdem, ein Verweis auf eine Musterlösung mit anderen Beispielen wäre sehr viel hilfreicher gewesen als Beiträge die
a) sich gegenseitig widersprechen (Zitat: "Comparable ist da aber ein schlechtes Stichwort, das ist etwas völlig anderes als nur "Gleichheit" und auch in diesem Fall mehr als schlecht geeignet 😉")
b) nur Stichwörter enthalten für die ich dann weitere Stunden Zeit investieren muss um eine Lösung zu finden.
 
Zuletzt bearbeitet:
Equals ist unabhängig von hashcode. Damit funktioniert equals immer.

Aber es gibt Regeln, die immer erfüllt sein sollten. Wenn zwei Objekte gleich sind, dann sollten sie auch den gleichen hashcode haben.

Das liegt einfach an der speziellen Verwendung von hashcode.

Dies kann z.B. zum schnellen identifizieren benutzt werden:
- Man speichert alle Objekte zusammen mit dem Hashcode. Dann kann man die Elemente sortiert vorhalten. Wenn man nun nach einem Element sucht, dann kann man die sortierten Hashcodes schnell durchgehen und muss dann nur noch wenige Elemente vergleichen. (Stell dir mal eine komplexe Klasse vor, bei der Du sehr viel vergleichen musst. So ein hashcode ist deutlich schneller verglichen!
- Das geht so weit, dass man Elemente einfach zusammen packt nach HashCode. HashMap und so sind da ein Beispiel. Da werden einfach n "Eimer" definiert und dann kommen die Key/Value Pare in den Eimer mit der Nummer key.hashcode % n ...
- ...

Das nur als einfache Erläuterung, wieso es wichtig ist, mit equals auch immer den hashcode zu überschreiben. Zur Not geht man so weit, dass man nur noch eine Konstante zurück gibt als Hashcode. Dann sind entsprechende Klassen sehr schlecht von der Performance aber es funktioniert alles ...

Und da sieht man dann auch gleich den Sinn, wieso es Sinn machen kann, Dinge immutable zu gestalten: Wenn Du etwas als Key in einer HashMap verwendest und dann änderst Du den key: Dann ist der Key plötzlich beim falschen Hashcode gespeichert und kann nicht mehr gefunden werden ...
 
Funktioniert in diesem Fall, ohne hashcode() zu überschreiben. Zufall oder geht das immer ohne den hashcode() zu überschreiben?
Solange du nur equals benutzt, funktioniert das natürlich, ohne dass du hashCode überschreibst. Aber es wäre komisch, wenn equals sagt, dass zwei Objekte gleich sind, aber hashCode ihnen unterschiedliche Werte gibt (also sagt, dass sie ungleich sind).

(geschrieben, bevor ich den Beitrag vo Kneitzel gelesen habe)
 
Generell wird es im richtigen Leben auch verdammt selten vorkommen das man den kompletten Inhalt eines komplexen Objekts auf Gleichheit überprüfen muss. Mir ist das bis jetzt jedenfalls noch nie vorgekommen
Kommt ganz drauf an, ab wann man Objekte als "komplex" bezeichnet.

Ich würde in meinem Code auf knapp 50/50 tippen, wobei die meisten Klassen gar keine equals-Methode haben. In normalem Code ist es eigentlich immer "eins oder alle".
 
Außerdem, ein Verweis auf eine Musterlösung mit anderen Beispielen wäre sehr viel hilfreicher gewesen als Beiträge die
Gibt keine einfache Musterlösung für equals.
Es gibt zwei in einem relevanten Punkt andere Varianten, und unabhängig davon kann man es zusätzlich auf zig andere Varianten schreiben, ich zb hätte es anders geschrieben (was in dem Fall für Randfälle auch zu anderem Verhalten führen würde) 🙂

Das Ding ist auch: die Musterlösung muss man verstehen. Und verstehst du dabei, warum man getClass() != o.getClass() und auch Double.compare(rechteck.laenge, laenge) == 0 nutzt, anstatt die Alternativen dazu?
Und, wichtiger: weißt, was sich draus dann als Folge für deinen Code ergibt?

a) sich gegenseitig widersprechen (Zitat: "Comparable ist da aber ein schlechtes Stichwort, das ist etwas völlig anderes als nur "Gleichheit" und auch in diesem Fall mehr als schlecht geeignet 😉")
Hätte ich lieber einen sehr ungeeigneten Vorschlag, der in diesem Fall "falsch" ist, ohne Widerspruch stehen lassen sollen? 😉
@Kirby_Sike ist selbst noch relativ neu in dem Thema, und Comparable ist durchaus ein Punkt, der einem da schnell in den Sinn kommt – aber es ist in diesem Fall halt wenig sinnvoll und da muss man durchaus drauf hinweisen.
 
Hätte ich lieber einen sehr ungeeigneten Vorschlag, der in diesem Fall "falsch" ist, ohne Widerspruch stehen lassen sollen?

Sorry, falsche Wortwahl. Ich meinte nicht "gegenseitig widersprechen", sondern "unterschiedliche Aussagen". 🙁
Vieles in Java ist unglaublich schwierig nachzuvollziehen und zeitraubend.

Und verstehst du dabei, warum man getClass() != o.getClass() und auch Double.compare(rechteck.laenge, laenge) == 0 nutzt, anstatt die Alternativen dazu?

Du hast mich durchschaut. Ich habe wirklich keine Ahnung wozu getClass() != o.getClass() und Double.compare(rechteck.laenge, laenge) == 0 genutzt wird.

Für mich als Anfänger ist es unverständlich, wieso Java so kompliziert sein muss.

Bestes Beispiel: Mein Taschenrechner kann zwei Gleitkommazahlen zuverlässig addieren, Java kann es nicht (der Grund ist mir mittlerweile bekannt).
 
Sorry, falsche Wortwahl. Ich meinte nicht "gegenseitig widersprechen", sondern "unterschiedliche Aussagen". 🙁
Vieles in Java ist unglaublich schwierig nachzuvollziehen und zeitraubend.



Du hast mich durchschaut. Ich habe wirklich keine Ahnung wozu getClass() != o.getClass() und Double.compare(rechteck.laenge, laenge) == 0 genutzt wird.

Für mich als Anfänger ist es unverständlich, wieso Java so kompliziert sein muss.

Bestes Beispiel: Mein Taschenrechner kann zwei Gleitkommazahlen zuverlässig addieren, Java kann es nicht (der Grund ist mir mittlerweile bekannt).
Kann dein Taschenrechner nicht. Der kann keine Gleitkommazahlen (bzw. wenn nicht genau). Der hat nur eine begrenzte Anzahl an Stellen - damit ist keine echte Gleitkommazahl 🙂

Programmiersprachen sind nun mal grundsätzlich komplex, weil man damit auch komplexe Dinge machen kann.
 
Bestes Beispiel: Mein Taschenrechner kann zwei Gleitkommazahlen zuverlässig addieren, Java kann es nicht (der Grund ist mir mittlerweile bekannt).
Beispiel wofür? Das Du doch noch kein Verständnis für die Problematik hast?

Wie kommst Du auf die Idee, dass der Taschenrechner etwas kann, das Java nicht kann?

Was die mathematischen Fähigkeiten angeht, geht alles zurück auf die Fähigkeiten der CPU. Glaubst Du wirklich, dass die CPU eines Taschenrechners mehr kann als die CPU eines Computers? Oder dass die irgend etwas grundsätzlich anders machen?

Somit ist das doch eher eine Problematik, die bei dem Entwickler liegt (Sprich: Da hat jemand schlicht einen Fehler gemacht, so das Ergebnis nicht den Anforderungen entspricht!)

Die Addition von Zahlen nehme ich einfach einmal als Beispiel:
Java:
public class Test {
    public static void main(String[] args) {
        double diff = 0.3;
        double d1 = 0;
        double d2 = 0;
        for (int i = 0; i < 1000; i++) {
            d1 = d1 + diff;
            d2 = round(d2 + diff);
        }

        System.out.println(d1);
        System.out.println(d2);
    }

    static double round(double value) {
        int decimalPoints = 10;
        double d = Math.pow(10, decimalPoints);
        return Math.rint(value * d) / d;
    }
}

0.3 habe ich als Wert genommen, da diese sich nicht dual darstellen lassen kann. Damit hat man eine Ungenauigkeit in der Zahl, die bei der Anzeige erst entfällt. Durch mehrfache Addition addiert sich diese Ungenauigkeit. Dies sieht man an d1 - da wird nichts behoben.
Bei d2 wird dies dann ständig korrigiert, denn es wird bei allen Zahlen immer auf 10 Nachkommastellen gekürzt und die Ungenauigkeit kann nicht in den Anzeigebereich wandern. ==> Problem einfach gelöst.

Ich kann aber auch jederzeit dazu übergehen, die Zahlen im 10er System darzustellen. Dann erhalte ich diese Probleme nicht erst.
Sprich: ich habe ich einen Zahlentyp, der Mantisse und Exponent in long Variablen speichert (nur als Idee).
Und die Mantisse ist dann eine Zahle wie -1234 und Exponent -2, was dann -1,234 * 10^-2 entsprechen würde, also -0,01234.
Die Rechenoperationen bildet man dann 1:1 so ab, wie eine CPU es mit gleitkommazahlen macht und schon habe ich eine Klasse geschrieben, mit der ich diese Berechnungen auch ausführen kann...

Also gleich zwei Ideen. Beide ganz einfach abgeleitet von dem Wissen zu Gleitkommazahlen und dem Verständnis des Problems.
 
Ein ganz klein wenig muss ich dem TE auch Recht geben. Manchmal wird in diesem Forum schon kryptisch um den Brei herum geredet, anstatt einfach auf eine Frage zu antworten. Ich kann mich da auch nicht ausnehmen, weil ich das auch öfter mache 🙁

zur Zeit habe ich Schwierigkeiten Objekt1.equals(Objekt2) zu verstehen.

Die Antwort dazu ist, dass jede Klasse in Java implizit von der "Mutter aller Klassen", der Klasse "Object", erbt. Die Klasse Object bietet eine Implementation der Methode equals() an, die allerdings nur vergleicht, ob es sich um genau die selben Objekte handelt.

Möchte man dieses Verhalten für seine Klassen anpassen, dann muss man die Methode equals() überschreiben. Die Regeln dafür finden sich in der Dokumentation: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)

Hier wird auch eine weitere Regel erwähnt: Wer equals() überschreibt, sollte immer auch hashCode() überschreiben.
 
Zuletzt bearbeitet:
Manchmal wird in diesem Forum schon kryptisch um den Brei herum geredet, anstatt einfach auf eine Frage zu antworten.
Das liegt aber IMO einfach daran, dass man entweder den Kenntnisstand des Fragenden nicht kennt, das Forum weder ein Java-Buch noch einen Java-Kurs ersetzen kann und/oder man dem TE helfen will, möglichst selbständig Lösungen zu erarbeiten.

Hier gab es die konkrete Frage, warum equals für zwei Object-Instanzen false liefert und die Frage wurde inkl. seiner Nachfrage aus #3 in Kommentar #4 vollständig beantwortet. Der Rest gehört dann wohl eher in die Kategorie "Java-Kurs".
 

Zurück
Oben