J'utilise Eclipse pour générer .equals()
et .hashCode()
, et il existe une option intitulée "Utiliser 'instanceof' pour comparer les types". Par défaut, cette option est décochée et utilisée .getClass()
pour comparer les types. Y at - il raison que je préférerais .getClass()
plus instanceof
?
Sans utiliser instanceof
:
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Utilisation instanceof
:
if (obj == null)
return false;
if (!(obj instanceof MyClass))
return false;
Je coche habituellement l' instanceof
option, puis j'entre et je supprime le " if (obj == null)
" chèque. (Il est redondant car les objets nuls échoueront toujours instanceof
.) Y a-t-il une raison pour laquelle c'est une mauvaise idée?
x instanceof SomeClass
est fausse six
c'estnull
. Par conséquent, la deuxième syntaxe n'a pas besoin de la vérification nulle.Réponses:
Si vous utilisez
instanceof
, ce qui rend votreequals
mise en œuvrefinal
préservera le contrat de symétrie de la méthode:x.equals(y) == y.equals(x)
. Si celafinal
semble restrictif, examinez attentivement votre notion d'équivalence d'objet pour vous assurer que vos implémentations prédominantes maintiennent pleinement le contrat établi par laObject
classe.la source
final
semble restrictif" (sur les deuxequals
ethashCode
) alors utiliser l'getClass()
égalité au lieu deinstanceof
afin de préserver les exigences de symétrie et de transitivité duequals
contrat.Josh Bloch privilégie votre approche:
Voir aussi cette réponse SO .
Le chapitre 3 de Effective Java couvre également cela.
la source
getClass
ne viole pas le LSP, puisque le LSP se rapporte simplement à ce qui peut être fait avec des instances existantes - pas aux types d'instances qui peuvent être construites. La classe renvoyée pargetClass
est une propriété immuable d'une instance d'objet. Le LSP n'implique pas qu'il devrait être possible de créer une sous-classe où cette propriété indique une classe autre que celle qui l'a créée.Angelika Langers Secrets of equal entre dans cela avec une discussion longue et détaillée pour quelques exemples courants et bien connus, y compris par Josh Bloch et Barbara Liskov, découvrant quelques problèmes dans la plupart d'entre eux. Elle obtient également dans le
instanceof
contregetClass
. Quelques citationsla source
La raison de l'utilisation
getClass
est d'assurer la propriété symétrique duequals
contrat. De Equals 'JavaDocs:En utilisant instanceof, il est possible de ne pas être symétrique. Prenons l'exemple: Dog étend Animal. Animal's
equals
effectue uneinstanceof
vérification d'Animal. Dog'sequals
fait uneinstanceof
vérification de Dog. Donnez Animal a et Chien d (avec les autres champs identiques):Cela viole la propriété symétrique.
Pour suivre strictement le contrat d'égal, la symétrie doit être assurée, et donc la classe doit être la même.
la source
a.equals(c)
etb.equals(c)
, alorsa.equals(b)
(l'approche naïve de faireDog.equals
justereturn super.equals(object)
quand!(object instanceof Dog)
mais de vérifier les champs supplémentaires quand il s'agit d'une instance de Dog ne violerait pas la symétrie mais violerait la transitivité)getClass()
vérification d'égalité, ou vous pouvez utiliser uneinstanceof
vérification si make yourequals
ethashCode
méthodesfinal
.C'est en quelque sorte un débat religieux. Les deux approches ont leurs problèmes.
Bloch a un autre conseil pertinent dans Effective Java Second Edition :
la source
getClass
ne violerait le LSP, à moins que la classe de base ne documente spécifiquement un moyen par lequel il devrait être possible de rendre les instances de différentes sous-classes qui se comparent égales. Quelle violation de LSP voyez-vous?getClass()
ne devrait pas être considéré comme significatif au-delà du fait que la classe en question est convertible en classe de base, le retour degetClass()
devrait être considéré comme toute autre propriété qui doit correspondre pour que les instances soient égales.Corrigez-moi si je me trompe, mais getClass () sera utile lorsque vous voulez vous assurer que votre instance n'est PAS une sous-classe de la classe avec laquelle vous comparez. Si vous utilisez instanceof dans cette situation, vous ne pouvez PAS le savoir car:
la source
Si vous voulez vous assurer que seule cette classe correspondra, utilisez
getClass() ==
. Si vous souhaitez faire correspondre des sous-classes, ilinstanceof
est nécessaire.En outre, instanceof ne correspondra pas à un null mais peut être comparé en toute sécurité à un null. Vous n'avez donc pas besoin de le vérifier.
la source
Cela dépend si vous considérez si une sous-classe d'une classe donnée est égale à son parent.
ici, j'utiliserais 'instanceof', car je veux qu'un LastName soit comparé à FamilyName
ici, j'utiliserais «getClass», car la classe dit déjà que les deux instances ne sont pas équivalentes.
la source
instanceof fonctionne pour les instances de la même classe ou ses sous-classes
ArryaList et RoleList sont tous deux instances de List
Tandis que
getClass () == o.getClass () ne sera vrai que si les deux objets (this et o) appartiennent exactement à la même classe.
Donc, en fonction de ce que vous devez comparer, vous pouvez utiliser l'un ou l'autre.
Si votre logique est: "Un objet est égal à un autre seulement s'ils sont tous les deux de la même classe", vous devriez opter pour les "égaux", ce qui, je pense, est la plupart des cas.
la source
Les deux méthodes ont leurs problèmes.
Si la sous-classe change l'identité, vous devez comparer leurs classes réelles. Sinon, vous violez la propriété symétrique. Par exemple, différents types de
Person
s ne doivent pas être considérés comme équivalents, même s'ils portent le même nom.Cependant, certaines sous-classes ne changent pas d'identité et doivent être utilisées
instanceof
. Par exemple, si nous avons un tas d'Shape
objets immuables , alors unRectangle
avec une longueur et une largeur de 1 devrait être égal à l'unitéSquare
.En pratique, je pense que le premier cas est plus vraisemblablement vrai. Habituellement, le sous-classement est une partie fondamentale de votre identité et être exactement comme votre parent sauf que vous pouvez faire une petite chose ne vous rend pas égal.
la source
En fait, instanceof vérifie où un objet appartient à une hiérarchie ou non. ex: l'objet Car appartient à la classe Vehical. Donc "nouvelle instance Car () de Vehical" renvoie true. Et "new Car (). GetClass (). Equals (Vehical.class)" renvoie false, bien que l'objet Car appartienne à la classe Vehical mais il est catégorisé comme un type distinct.
la source