[Zum Zeitpunkt dieses Schreibens wurden drei weitere Antworten veröffentlicht.]
Um es noch einmal zu wiederholen, das Ziel meiner Frage ist es, Standardfälle von Tests zu finden, um dies zu bestätigen hashCode
und equals
miteinander übereinzustimmen. Mein Ansatz für diese Frage besteht darin, mir die gemeinsamen Wege vorzustellen, die Programmierer beim Schreiben der fraglichen Klassen eingeschlagen haben, nämlich unveränderliche Daten. Zum Beispiel:
- Schrieb
equals()
ohne zu schreiben hashCode()
. Dies bedeutet häufig, dass Gleichheit als Gleichheit der Felder zweier Instanzen definiert wurde.
- Schrieb
hashCode()
ohne zu schreiben equals()
. Dies könnte bedeuten, dass der Programmierer nach einem effizienteren Hashing-Algorithmus suchte.
Im Fall von # 2 scheint mir das Problem nicht zu existieren. Es wurden keine zusätzlichen Instanzen erstellt equals()
, daher sind keine zusätzlichen Instanzen erforderlich, um gleiche Hash-Codes zu haben. Im schlimmsten Fall kann der Hash-Algorithmus zu einer schlechteren Leistung für Hash-Maps führen, was außerhalb des Rahmens dieser Frage liegt.
Im Fall von # 1 umfasst der Standard-Komponententest das Erstellen von zwei Instanzen desselben Objekts mit denselben Daten, die an den Konstruktor übergeben werden, und das Überprüfen gleicher Hash-Codes. Was ist mit Fehlalarmen? Es ist möglich, Konstruktorparameter auszuwählen, die zufällig gleiche Hash-Codes auf einem dennoch unsoliden Algorithmus ergeben. Ein Unit-Test, der dazu neigt, solche Parameter zu vermeiden, würde den Geist dieser Frage erfüllen. Die Abkürzung hier besteht darin, den Quellcode zu überprüfen, gründlich equals()
nachzudenken und einen darauf basierenden Test zu schreiben. In einigen Fällen kann dies zwar erforderlich sein, es kann jedoch auch allgemeine Tests geben, die häufig auftretende Probleme auffangen - und solche Tests erfüllen auch den Geist dieser Frage.
Wenn die zu testende Klasse (nennen Sie sie Daten) beispielsweise einen Konstruktor hat, der einen String akzeptiert, und Instanzen, die aus Strings erstellt wurden und Instanzen equals()
ergeben, die es waren equals()
, würde ein guter Test wahrscheinlich Folgendes testen:
new Data("foo")
- Ein weiterer
new Data("foo")
Wir könnten sogar den Hash-Code überprüfen new Data(new String("foo"))
, um zu erzwingen, dass der String nicht interniert wird, obwohl dies Data.equals()
meiner Meinung nach eher zu einem korrekten Hash-Code als zu einem korrekten Ergebnis führt.
Die Antwort von Eli Courtwright ist ein Beispiel dafür, wie man überlegt, wie man den Hash-Algorithmus auf der Grundlage der Kenntnis der equals
Spezifikation brechen kann . Das Beispiel einer speziellen Sammlung ist gut, da benutzerdefinierte Collection
s manchmal auftauchen und im Hash-Algorithmus sehr anfällig für Fehler sind.