Frage

Diese Frage speziell auf Überschreiben der Methode equals () für Objekte mit einer großen Anzahl von Feldern. Zunächst einmal möchte ich sagen, dass dieses große Objekt nicht nach unten in mehrere Komponenten zerlegt werden kann, ohne OO Prinzipien zu verletzen, so sagt mir helfen wird, nicht „keine Klasse sollte mehr als x Felder haben“.

Umzug auf, kam das Problem zum Tragen, wenn ich vergessen habe, eines der Felder für die Gleichstellung zu überprüfen. Deshalb war meine Methode equals falsch. Dann dachte ich Reflektion zu verwenden:

--code removed because it was too distracting--

Der Zweck dieser Stelle ist nicht unbedingt den Code Refactoring (dies ist nicht einmal der Code ich verwende), sondern stattdessen Eingang auszukommen, ob dies eine gute Idee ist.

Vorteile:

  • Wenn ein neues Feld hinzugefügt wird, wird es automatisch eingeschlossen
  • Die Methode ist viel mehr lapidar als 30 if-Anweisungen

Nachteile:

  • Wenn ein neues Feld hinzugefügt wird, wird es automatisch enthalten, manchmal ist dies nicht wünschenswert
  • Performance: Das hat langsamer sein, ich fühle mich nicht die Notwendigkeit, einen Profiler auszubrechen
  • Whitelisting bestimmte Felder im Vergleich zu ignorieren ist ein wenig hässlich

Alle Gedanken?

War es hilfreich?

Lösung

Wenn Sie aus Performance-Gründen wollte die weiße Liste, sollten Sie eine Anmerkung mit um anzuzeigen, welche zu vergleichen Felder. Außerdem wird diese Implementierung nicht funktionieren, wenn Sie Ihre Felder keine gute Implementierungen für equals().

P. S. Wenn Sie diesen Weg für equals() gehen, vergessen Sie nicht etwas ähnliches für hashCode() zu tun.

P.P.S. Ich vertraue Ihnen bereits als HashCodeBuilder und Equals .

Andere Tipps

Mit Eclipse FFS!

Löschen Sie die hashCode und gleich Methoden, die Sie haben.

Rechtsklick auf die Datei.

Wählen Sie Quelle-> Gene hashcode und gleich ...

Fertig! Keine Sorgen mehr über Reflexion.

Wiederholen Sie für jedes Feld hinzugefügt haben, verwenden Sie nur die Gliederungsansicht Ihre beiden Methoden zu löschen, und dann lassen Eklipse sie automatisch generieren.

Wenn Sie die Reflexion Ansatz gehen tun, Equals ist immer noch dein Freund:

 public boolean equals(Object obj) {
    return EqualsBuilder.reflectionEquals(this, obj);
 }

Hier ist ein Gedanke, wenn Sie sich Sorgen über:

1 / Vergessen Ihrer große Serie aktualisieren von if-Anweisungen für die Gleichstellung prüft, wenn Sie ein Feld hinzufügen / entfernen.

2 / Die Leistung dieses in den Gleichen zu tun () -Methode.

Versuchen Sie Folgendes:

a / Revert zurück, um die lange Folge von if-Anweisungen in Ihrem equals () -Methode verwendet wird.

b / hat eine einzige Funktion, die eine Liste der Felder (in einer String-Array) enthält und die Liste an der Realität überprüfen wird (d.h., die reflektierten Felder). Es wird eine Ausnahme aus, wenn sie nicht übereinstimmen.

c / In Ihrem Konstruktor für dieses Objekt haben eine synchronisierte Lauf einmal auf diese Funktion aufrufen (ähnlich einem Singletonmuster). Mit anderen Worten, wenn dies das erste Objekt von dieser Klasse konstruiert ist, rufen Sie die Prüffunktion in (b).

Die Ausnahme wird es sofort klar, wenn Sie Ihr Programm ausführen, wenn Sie Ihre if-Aussagen nicht aktualisiert haben die reflektierten Felder entsprechen; dann beheben Sie die if-Anweisungen und die Feldliste aktualisieren aus (b).

Im Anschluss Bau von Objekten wird diese Prüfung und Ihre equals nicht tun () -Methode wird es laufen ist maximal mögliche Geschwindigkeit.

Versuchen Sie, wie ich könnte, ich habe (mehr Köpfe auf Stackoverflow existieren kann) nicht in der Lage gewesen, keine wirklichen Probleme mit diesem Ansatz zu finden - es gibt eine zusätzliche Bedingung Prüfung an jedem Objekt Konstruktion für das Lauf einmal Verhalten, aber das scheint ziemlich Moll.

Wenn Sie hart genug versuchen, könnten Sie immer noch Ihre if-Anweisungen aus Schritt mit Ihrer Feldliste erhalten und reflektierten Felder aber die Ausnahme wird dafür sorgen, Ihre Feldliste der reflektierten Felder übereinstimmt und Sie nur sicherstellen, dass Sie die wenn- aktualisieren Aussagen und Feldliste zur gleichen Zeit.

Sie können mit Anmerkungen versehen immer die Felder, die Sie / wollen nicht in Ihrer Methode equals, das eine einfache und einfache Änderung es sein sollte.

Die Leistung wird offenbar damit zusammen, wie oft das Objekt tatsächlich verglichen wird, aber eine Menge von Frameworks verwenden Hash-Karten, so dass Ihre Gleichen verwendet wird, kann mehr sein wird, als Sie denken.

Auch spricht von Hash-Karten, haben Sie das gleiche Problem mit der Methode hashCode.

Schließlich tun Sie wirklich alle Felder für die Gleichstellung müssen vergleichen?

Sie haben ein paar Fehler in Ihrem Code.

  1. Sie können nicht davon ausgehen, dass this und obj ist die gleiche Klasse. Tatsächlich ist es ausdrücklich erlaubt für obj jede andere Klasse. Sie könnten mit if ( ! obj instanceof myClass ) return false; beginnen aber das ist immer noch nicht richtig , weil obj eine Unterklasse von this mit zusätzlichen Feldern sein könnte, dass die Materie könnte.
  2. Sie müssen null Werte für obj mit einem einfachen if ( obj == null ) return false;
  3. Unterstützung
  4. Sie können nicht null und leere Zeichenfolge als gleich behandeln. Stattdessen behandeln null speziell. Einfachste Weg, hier ist durch den Vergleich Field.get(obj) == Field.get(this) zu starten. Wenn sie beide gleich oder beide sind zufällig das gleiche Objekt zeigen, ist dies schnell. (Hinweis: Dies ist auch eine Optimierung, die Sie benötigen, da dies eine langsame Routine.) Wenn dies nicht gelingt, können Sie die schnellen if ( Field.get(obj) == null || Field.get(this) == null ) return false; können Fälle zu behandeln, wo genau ein null ist. Schließlich können Sie die üblichen equals() verwenden.
  5. Sie sind nicht mit foundMismatch

ich mit Hank darüber einig, dass [HashCodeBuilder][1] und [EqualsBuilder][2] einen besseren Weg zu gehen. Es ist leicht zu pflegen, nicht viel Standardcode, und Sie vermeiden, all diese Probleme.

Sie können Anmerkungen verwenden, um Felder von der Prüfung ausschließen

z.

@IgnoreEquals
String fieldThatShouldNotBeCompared;

Und dann überprüfen Sie natürlich das Vorhandensein der Anmerkung in Ihrer generischen Methode equals.

Wenn Sie den Zugriff auf die Namen der Felder haben, warum Sie nicht machen es zu einem Standard, den Sie Felder wollen nicht immer schließen beginnen mit „local“ oder „nochk“ oder so ähnlich.

Dann schwarze Liste Sie alle Felder, die mit diesem beginnen (Code ist nicht so hässlich, dann).

Ich zweifle nicht, es ist ein wenig langsamer. Sie müssen entscheiden, ob Sie Einfachheit des Updates gegen die Ausführungsgeschwindigkeit tauschen wollen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top