Używam Eclipse do generowania .equals()
i .hashCode()
, i jest opcja oznaczona jako „Użyj„ instanceof ”, aby porównać typy”. Domyślnie ta opcja jest odznaczona i używana .getClass()
do porównywania typów. Czy jest jakiś powód powinien Wolę .getClass()
ponad instanceof
?
Bez użycia instanceof
:
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Używając instanceof
:
if (obj == null)
return false;
if (!(obj instanceof MyClass))
return false;
Zwykle zaznaczam instanceof
opcję, a następnie wchodzę i usuwam if (obj == null)
zaznaczenie. (Jest to zbędne, ponieważ puste obiekty zawsze zawodzą instanceof
). Czy jest jakiś powód, dla którego to zły pomysł?
java
eclipse
equals
instanceof
Wyrko
źródło
źródło
x instanceof SomeClass
jest fałszywe, jeślix
jestnull
. W związku z tym druga składnia nie wymaga sprawdzania wartości null.Odpowiedzi:
Jeśli używasz
instanceof
, dzięki czemuequals
wdrażaniefinal
zachowa umowę symetrii metody:x.equals(y) == y.equals(x)
. Jeślifinal
wydaje się to restrykcyjne, dokładnie przeanalizuj swoje pojęcie równoważności obiektów, aby upewnić się, że nadpisujące implementacje w pełni obsługują kontrakt ustanowiony przezObject
klasę.źródło
final
wydaje się restrykcyjne” (w obu przypadkachequals
ihashCode
), należy użyćgetClass()
równości zamiastinstanceof
, aby zachować wymagania dotyczące symetrii i przechodniościequals
kontraktu.Josh Bloch popiera Twoje podejście:
Zobacz także tę odpowiedź SO .
Efektywna Java rozdział 3 również to obejmuje.
źródło
getClass
nie narusza LSP, ponieważ LSP odnosi się jedynie do tego, co można zrobić z istniejącymi instancjami, a nie do tego, jakiego rodzaju instancje można skonstruować. Klasa zwrócona przezgetClass
jest niezmienną właściwością instancji obiektu. LSP nie oznacza, że powinno być możliwe utworzenie podklasy, w której ta właściwość wskazuje inną klasę niż ta, która ją utworzyła.Angelika Langers Tajemnice równości wkraczają w to po długiej i szczegółowej dyskusji kilku popularnych i dobrze znanych przykładów, w tym autorstwa Josha Blocha i Barbary Liskov, odkrywając w większości z nich kilka problemów. Wstaje również Into the
instanceof
vsgetClass
. Jakiś cytat z tegoźródło
Celem stosowania
getClass
jest zapewnienie symetrycznościequals
umowy. Z równych dokumentów JavaDocs:Używając instanceof, można nie być symetrycznym. Rozważmy przykład: Pies rozszerza Animal. Zwierzęcia
equals
robi sięinstanceof
kontrolę zwierzęcia. Psaequals
robi toinstanceof
sprawdzenie Dog. Daj Zwierzę a i Pies d (z innymi polami to samo):Narusza to właściwość symetrii.
Aby ściśle przestrzegać kontraktu równego, należy zapewnić symetrię, a zatem klasa musi być taka sama.
źródło
a.equals(c)
ib.equals(c)
wtedya.equals(b)
(naiwne podejście polegające na robieniuDog.equals
tylkoreturn super.equals(object)
wtedy,!(object instanceof Dog)
ale sprawdzanie dodatkowych pól, gdy jest to instancja Dog, nie naruszyłoby symetrii, ale naruszyłoby przechodniość)getClass()
testu równości lub możesz użyćinstanceof
czeku, jeśli maszequals
ihashCode
metodyfinal
.To coś w rodzaju debaty religijnej. Oba podejścia mają swoje problemy.
Bloch ma kolejną istotną radę w Effective Java Second Edition :
źródło
getClass
nie naruszałoby LSP, chyba że klasa bazowa wyraźnie udokumentowała sposób, za pomocą którego powinno być możliwe uczynienie instancji różnych podklas, które porównują się równo. Jakie naruszenie LSP widzisz?getClass()
nie powinno to być uważane za znaczące poza faktem, że dana klasa jest konwertowalna na klasę bazową, zwrot zgetClass()
powinien być traktowany jak każda inna właściwość, która musi być zgodna, aby wystąpienia były równe.Popraw mnie, jeśli się mylę, ale metoda getClass () przyda się, gdy chcesz się upewnić, że Twoja instancja NIE jest podklasą klasy, z którą porównujesz. Jeśli używasz w takiej sytuacji instanceof, NIE możesz tego wiedzieć, ponieważ:
źródło
Jeśli chcesz mieć pewność, że tylko ta klasa będzie pasować, użyj
getClass() ==
. Jeśli chcesz dopasować podklasy,instanceof
jest to potrzebne.Ponadto instanceof nie pasuje do wartości null, ale można ją bezpiecznie porównać z wartością null. Więc nie musisz tego sprawdzać.
źródło
Zależy to od tego, czy weźmiesz pod uwagę, czy podklasa danej klasy jest równa swojej klasie macierzystej.
tutaj użyłbym „instanceof”, ponieważ chcę, aby LastName był porównywany z FamilyName
tutaj użyłbym „getClass”, ponieważ klasa mówi już, że te dwa wystąpienia nie są równoważne.
źródło
instanceof działa dla instancji tej samej klasy lub jej podklas
ArryaList i RoleList są instancjami listy
Podczas
getClass () == o.getClass () będzie prawdziwe tylko wtedy, gdy oba obiekty (this i o) należą do dokładnie tej samej klasy.
Więc w zależności od tego, co chcesz porównać, możesz użyć jednego lub drugiego.
Jeśli Twoja logika brzmi: „Jeden obiekt jest równy drugiemu tylko wtedy, gdy oba należą do tej samej klasy”, powinieneś wybrać „równe”, co moim zdaniem jest w większości przypadków.
źródło
Obie metody mają swoje problemy.
Jeśli podklasa zmieni tożsamość, musisz porównać ich rzeczywiste klasy. W przeciwnym razie naruszysz właściwość symetrii. Na przykład różne typy
Person
znaków nie powinny być uważane za równoważne, nawet jeśli mają taką samą nazwę.Jednak niektóre podklasy nie zmieniają tożsamości i trzeba ich używać
instanceof
. Na przykład, jeśli mamy kilka niezmiennychShape
obiektów, to aRectangle
o długości i szerokości 1 powinno być równe jednostceSquare
.W praktyce myślę, że ten pierwszy przypadek jest bardziej prawdopodobny. Zwykle tworzenie podklas jest fundamentalną częścią twojej tożsamości, a bycie dokładnie takim jak twój rodzic, z wyjątkiem jednej małej rzeczy, nie czyni cię równym.
źródło
Właściwie instancja sprawdzenia, czy obiekt należy do jakiejś hierarchii, czy nie. np .: obiekt samochodowy należy do klasy pojazdów. Zatem „new Car () instancja klasy Vehical” zwraca wartość true. A „new Car (). GetClass (). Equals (Vehical.class)” zwraca false, chociaż obiekt Car należy do klasy Vehical, ale jest sklasyfikowany jako oddzielny typ.
źródło