Ich verwende Eclipse zum Generieren von .equals()
und .hashCode()
und es gibt eine Option mit der Bezeichnung "Verwenden Sie 'instanceof' zum Vergleichen von Typen". Standardmäßig ist diese Option deaktiviert und wird .getClass()
zum Vergleichen von Typen verwendet. Gibt es einen Grund , warum ich es vorziehen sollte .getClass()
über instanceof
?
Ohne zu verwenden instanceof
:
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Verwenden von instanceof
:
if (obj == null)
return false;
if (!(obj instanceof MyClass))
return false;
Normalerweise überprüfe ich die instanceof
Option und gehe dann hinein und entferne den " if (obj == null)
" Scheck. (Es ist redundant, da Nullobjekte immer fehlschlagen instanceof
.) Gibt es einen Grund, der eine schlechte Idee ist?
java
eclipse
equals
instanceof
Pennen
quelle
quelle
x instanceof SomeClass
ist falsch , wennx
istnull
. Daher benötigt die zweite Syntax keine Nullprüfung.Antworten:
Wenn Sie verwenden
instanceof
, wird bei Ihrerequals
Implementierungfinal
der Symmetrievertrag der Methode beibehalten :x.equals(y) == y.equals(x)
. Wenn diesfinal
restriktiv erscheint, überprüfen Sie sorgfältig Ihren Begriff der Objektäquivalenz, um sicherzustellen, dass Ihre übergeordneten Implementierungen den von derObject
Klasse festgelegten Vertrag vollständig beibehalten .quelle
final
es restriktiv erscheint" (für beideequals
undhashCode
) danngetClass()
Gleichheit anstelle voninstanceof
verwenden, um die Symmetrie- und Transitivitätsanforderungen desequals
Vertrags zu erhalten.Josh Bloch bevorzugt Ihren Ansatz:
Siehe auch diese SO-Antwort .
Effektives Java- Kapitel 3 behandelt dies ebenfalls.
quelle
getClass
verstößt nicht gegen den LSP, da sich der LSP lediglich darauf bezieht, was mit vorhandenen Instanzen getan werden kann - nicht darauf, welche Arten von Instanzen erstellt werden können. Die von zurückgegebene KlassegetClass
ist eine unveränderliche Eigenschaft einer Objektinstanz. Der LSP impliziert nicht, dass es möglich sein sollte, eine Unterklasse zu erstellen, in der diese Eigenschaft eine andere Klasse als die anzeigt, die sie erstellt hat.Angelika Langers Secrets of Equals geht darauf mit einer langen und detaillierten Diskussion einiger allgemeiner und bekannter Beispiele ein, darunter von Josh Bloch und Barbara Liskov, und entdeckt in den meisten von ihnen einige Probleme. Sie bekommt auch in den
instanceof
vsgetClass
. Einige zitieren darausquelle
Der Grund für die Verwendung
getClass
besteht darin, die symmetrische Eigenschaft desequals
Vertrags sicherzustellen . Aus den JavaDocs von equals:Durch die Verwendung von instanceof ist es möglich, nicht symmetrisch zu sein. Betrachten Sie das Beispiel: Hund erweitert Tier. Tier
equals
tut eineinstanceof
Überprüfung des Tieres. Hundequals
tut eineninstanceof
Scheck von Dog. Geben Sie Tier a und Hund d (mit anderen Feldern gleich):Dies verletzt die symmetrische Eigenschaft.
Um den Vertrag von Equal genau zu befolgen, muss die Symmetrie sichergestellt sein, und daher muss die Klasse dieselbe sein.
quelle
a.equals(c)
undb.equals(c)
danna.equals(b)
(der naive Ansatz,Dog.equals
nurreturn super.equals(object)
wann zu machen,!(object instanceof Dog)
aber die zusätzlichen Felder zu überprüfen, wenn es sich um eine Dog-Instanz handelt, würde die Symmetrie nicht verletzen, aber die Transitivität verletzen)getClass()
Gleichheitsprüfung verwenden, oder Sie können eineinstanceof
Prüfung verwenden, wenn Sie Ihreequals
undhashCode
Methoden erstellenfinal
.Dies ist so etwas wie eine religiöse Debatte. Beide Ansätze haben ihre Probleme.
Bloch hat einen weiteren relevanten Ratschlag in Effective Java Second Edition :
quelle
getClass
würde den LSP verletzen, es sei denn, die Basisklasse hat speziell ein Mittel dokumentiert, mit dem es möglich sein sollte, Instanzen verschiedener Unterklassen, die vergleichbar sind, gleich zu machen. Welche LSP-Verletzung sehen Sie?getClass()
nicht besagt, dass dies nicht über die Tatsache hinaus als sinnvoll angesehen werden sollte, dass die betreffende Klasse in die Basisklasse konvertierbar ist, sollte die Rückgabe vongetClass()
wie jede andere Eigenschaft betrachtet werden, die übereinstimmen muss, damit Instanzen gleich sind.Korrigieren Sie mich, wenn ich falsch liege, aber getClass () ist hilfreich, wenn Sie sicherstellen möchten, dass Ihre Instanz KEINE Unterklasse der Klasse ist, mit der Sie vergleichen. Wenn Sie in dieser Situation instanceof verwenden, können Sie das NICHT wissen, weil:
quelle
Wenn Sie sicherstellen möchten, dass nur diese Klasse übereinstimmt, verwenden Sie
getClass() ==
. Wenn Sie Unterklassen abgleichen möchten,instanceof
wird dies benötigt.Außerdem stimmt instanceof nicht mit einer Null überein, kann aber sicher mit einer Null verglichen werden. Sie müssen es also nicht null überprüfen.
quelle
Dies hängt davon ab, ob Sie berücksichtigen, ob eine Unterklasse einer bestimmten Klasse der übergeordneten Klasse entspricht.
Hier würde ich 'instanceof' verwenden, da ich möchte, dass ein Nachname mit dem Familiennamen verglichen wird
hier würde ich 'getClass' verwenden, da die Klasse bereits sagt, dass die beiden Instanzen nicht gleichwertig sind.
quelle
instanceof arbeitet für Instenzen derselben Klasse oder ihrer Unterklassen
ArryaList und RoleList sind beide Instanzen von List
Während
getClass () == o.getClass () ist nur wahr, wenn beide Objekte (this und o) genau derselben Klasse angehören.
Je nachdem, was Sie vergleichen müssen, können Sie das eine oder andere verwenden.
Wenn Ihre Logik lautet: "Ein Objekt ist nur dann gleich einem anderen, wenn beide dieselbe Klasse sind", sollten Sie sich für "gleich" entscheiden, was meiner Meinung nach in den meisten Fällen der Fall ist.
quelle
Beide Methoden haben ihre Probleme.
Wenn die Unterklasse die Identität ändert, müssen Sie ihre tatsächlichen Klassen vergleichen. Andernfalls verletzen Sie die symmetrische Eigenschaft. Beispielsweise sollten verschiedene Arten von
Person
s nicht als gleichwertig angesehen werden, selbst wenn sie denselben Namen haben.Einige Unterklassen ändern jedoch nicht die Identität und müssen verwendet werden
instanceof
. Wenn wir zum Beispiel eine Reihe unveränderlicherShape
Objekte haben, sollte aRectangle
mit einer Länge und Breite von 1 gleich der Einheit seinSquare
.In der Praxis denke ich, dass der erstere Fall eher wahr ist. Normalerweise ist die Unterklasse ein wesentlicher Bestandteil Ihrer Identität. Wenn Sie genau wie Ihre Eltern sind, außer dass Sie eine Kleinigkeit tun können, sind Sie nicht gleichberechtigt.
quelle
Tatsächlich wird geprüft, wo ein Objekt zu einer Hierarchie gehört oder nicht. Beispiel: Das Autoobjekt gehört zur Fahrzeugklasse. "New Car () Instanz von Vehical" gibt also true zurück. Und "new Car (). GetClass (). Equals (Vehical.class)" gibt false zurück, obwohl das Car-Objekt zur Vehical-Klasse gehört, aber als separater Typ kategorisiert ist.
quelle