HashCode korrekt

TomTank

Mitglied
Ich habe aus einem Programm folgende Codezeilen:

Java:
private Set<Link> links = new HashSet<>();
@Override
public int hashCode() {
int refidHashCode = refid.hashCode();
int linkHashCode =
link != null ? link.intValue() : (int)
Math.random();
return refidHashCode + linkHashCode;
}

@Override
public boolean equals(final Object obj) {
return Objects.equals(link, obj);
}

Ich frag mich gerad ob dieses korrekt implementiert ist.
 
Ich frag mich gerad ob dieses korrekt implementiert ist.
Also uns fehlen erst einmal viele Informationen - da werden Variablen genutzt, die wir nicht kennen.
Und auch die Regeln sind uns nicht bekannt. Wie soll es sich verhalten?

Aber es sieht extrem dubios aus:
- Ein Zufallswert bei hashCode? Was soll der Sinn dahinter sein?
- Equals vergleicht eine Instanzvariable des Wrapper Objekts mit dem Objekt? Das solltest Du mir ggf. auch einmal erklären.
- int refidHashCode = refidHashCode.hashCode(); Eine neue lokale Variable? Und in der Zuweisung eines Wertes nutzt du die Variable selbst? Und rufst auf einer int Variablen hashCode auf? Das wird sich vermutlich nicht übersetzen lassen.
 
Nein, das ist boese.

Solange link null ist wird ein *zufaelliger* Hash-Code retourniert, das bricht *jede* Logik.

Sieh dir mal die Dokumentation von Object.equals und Object.hashCode an, da steht drinnen welche Bedingungen genau erfuellt sein muessen. Als ergaenzung dazu rate ich zum Kapitel in Effective Java zu dem Thema.

Kurz: Folgende Bedingung muss immer gegeben sein a.equals(b) == (a.hashCode() == b.hashCode()). Also equals und hashCode muessen immer symmetrisch sein. Wenn die Objekte uebereinstimmen, muessen sie auch den gleichen Hash-Code haben. Wenn sie nicht uebereinstimmen, muessen sie unterschiedliche Hash-Codes haben. Wenn die nicht symmetrisch sind, zerbrichst du damit einen Haufen Klassen, unter anderem HashSet/HashMap, und das kann neben mieser Laufzeitleistung auch zu unerwarteten Ergebnissen fuehren. In diesem fall sogar zu unnachvollziehbaren weil Zufall mit drinnen ist.

Es wird sogar noch schlimmer, Math.random() liefert naemlich einen double. Durch das ternaere if wird dieser leise zu einem int geschnitten, und ist damit immer 0. Ohne das ternaere if wuerdest du den Fehler sehen und der Code wuerde nicht kompilieren.

Java:
int linkHashCode = Math.random(); // Compiler Fehler

@KonradN Das naechste Script wird eines, das feststellt das ich gerade im Thema tippe, und dann jedes mal deinen Browser abschieszt oder ausbremst wenn du auch tippen willst. 😉
 
Danke euch beiden. Ich habe den Quellcode auch nur aus einem anderen Programm und habe mir die gleichen Gedanken gemacht, war mir aber unsicher. - Ich fands auch etwas strange.
 
Zusätzlich, zu dem bereits geschriebenen: wenn Du in equals bereits Objects verwendest, warum nicht auch in hashCode? return Objects.hash(refid, link);
 
Da ich mir recht sicher bin, dass ich es per Copy & Paste kopiert habe, wird der Post noch einmal editiert worden sein.

Und ich meine mich zu erinnern, dass ein Post in den ersten Minuten editiert werden kann, ohne dass es angezeigt wird als editierter Beitrag.
 

Zurück
Oben