Wieso ist diese eigene Equals-Methode schlecht?

SexyPenny90

Mitglied
Hallo,

ich habe folgende equals-Methode geschrieben:
Java:
public class Something {
    private int attribute;

    public Something (int attribute) {
        this.attribute = attribute;
    }
    
    public boolean equals (Something other) {
        if (other == null) { return false; }
        if (other == this) { return true; }
        if (other.attribute == this.attribute) { return true; }
        return false;
    }
}

Angeblich, soll es bei gewissen Szenarien Probleme geben. Liegt das dann an der Zeile :
if (other == this) { return true; }
, weil nur die Objekte überprüft werden und nicht der Inhalt der Attribute?

mfg Penny
 
Zuletzt bearbeitet:
ne die ist imho völlig ok. wenn die referenz gleich ist, ist es auch das gleiche objekt.

[EDIT]
ne doch nicht 😉. signatur ist falsch. nutz @override dann passiert sowas nicht[/EDIT]
 
== bedeutet identisch.

Identisch: Zwei Objekte sind identisch, wenn sie beide das selbe Objekt (exakt am selben Ort im Speicher) referenzieren, was mittels "==" getestet wird. In der Objektorientierung heißt das auch, dass diese eine gemeinsame Instanz haben. Stellen Sie sich das einfach so vor, als wenn Hausnummern in einer Stadt verglichen werden: Die Hausnummern sind zwar gleich, aber es können verschiedene Leute im Haus wohnen.

Wenn du vergleichen willst, ob sie gleichen Inhalts sind, aber nicht identisch, dann musst du die einzelnen Variablen vergleichen
 
nein ist sie nicht. die methodensignatur ist falsch.

Java:
	@Override
	public boolean equals(Object obj) {
		if (obj == this) return true;
		if (obj == null) return false;
		if (getClass() != obj.getClass()) return false;
		
		return attribute == ((Something)obj).attribute;
	}
 
Java:
class Something
{
    private int attribut;
    
    @Override
    public boolean equals(Object other)
    {
        if (other instanceof Something)
        {
            Something SomeOther = (Something)other;
            return this.attribut == SomeOther.attribut;
        }
        return false;
    }

    @Override
    public int hashCode() 
    {
        return this.attribut;
    }
}

So müsste das funktionieren.
 
Ich verssteh nicht ganz wieso das nicht so geht.

Wenn ich ne klasse schreiben die so aussieht:

Java:
public class Testequal{

     public static void main(String[] args) {
        Something other = new Something(123);
        Something something = new Something(12);
        
        Boolean equals = something.equals(other));
    }
}
wird doch kein falsches Ergebnis raus kommen. Bei welchem Bsp. würde den ein Fehler auftreffen?
 
Hier z.B.:
Java:
Something st1 = new Something(23);
Object st2 = new Something(23);
System.out.println(st1.equals(st2));

Ergibt false da nicht deine equals-Methode aufgerufen wird - etwas anderes fällt mir adhoc nicht ein.
 
Was genau hindert dich daran, einfach mal die Doku zu lesen, wie eine equals-Methode auszusehen hat?

Object#equals

Ergänzend zu den Anmerkungen der anderen fehlt hier auch eindeutig die überschriebene hashCode-Methode.

Insgesamt mal wieder ein typischer Fall von RTFM
 
nö, wenn man das Überschreiben von equals lernt dann gleich richtig ...

kommt halt ganz drauf an, was man mit der klasse machen will. eine hashcode ohne equals macht wenig sinn, da geb ich dir recht. aber wenn man instanzen der klasse lediglich auf gleichheit überprüfen will, genügt auch nur die equals.

wenn man natürlich code schreibt, der von dritten verwendet wird, sollte man immer beides tun..
 
Klar, wenn man so argumentiert braucht man sich so ziemlich jedes vernünftige Programmieren erst gar nicht angewöhnen. Schließlich weiß man Glaskugel sei Dank ja ganz genau, dass der eigene Code für alle Ewigkeiten so bleibt, nie von einem selbst oder anderen verwendet wird und, um wieder auf equals/hashCode-Problematik zurückzukommen, irgendwelche Objekte auch niemals in Hash-basierten Sets oder Maps landen werden...
 
Tobias1501: Der Code mit [c]instanceof[/c] gegenüber [c]getClass().equals(...)[/c] würde gegen die Regeln verstossen. Wenn du da nämlich [c]Foo[/c] und [c]Bar -> Foo[/c] hättest, würde bei in Foo bekannten, korrekten Werten [c]Foo#equals()[/c] [c]true[/c] und [c]Bar#equals()[/c] [c]false[/c] liefern, korrekt wär aber [c]false[/c] in beiden Klassen.
 
Das stimmt in diesem Falle. Wenn die Klasse Foo allerdings final wäre, dann spart einem instanceof eine Überprüfung auf null und stimmt trotzdem immer 🙂

Dementsprechend gibt es für eine Equals-Methode zwei Varianten:

Finale Klasse
Java:
@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof MyClass)) {
        return false;
    }
    MyClass other = (MyClass) o;
    // Eqaul Vergleich der Attribute
}

Nicht-finale Klasse
Java:
@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null) {
        return false;
    }
    if (!getClass().equals(o.getClass())) {
        return false;
    }
    MyClass other = (MyClass) o;
    // Eqaul Vergleich der Attribute
}
 

Neue Themen


Zurück
Oben