Aucune raison de préférer getClass() sur instanceof lors de la génération .equals()?
J'utilise Eclipse pour générer .equals()
et .hashCode()
, et il y a une option intitulée "Utilisation" instanceof "pour comparer les types". La valeur par défaut pour cette option pour être désactivée et l'utilisation .getClass()
de comparer les types. Est-il une raison que je préférerais .getClass()
sur instanceof
?
Sans l'aide de instanceof
:
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
À l'aide de instanceof
:
if (obj == null)
return false;
if (!(obj instanceof MyClass))
return false;
J'ai l'habitude de vérifier la instanceof
option, puis retirer le "if (obj == null)
" vérifier. (Il est superflu, puisque les objets nuls échouera toujours instanceof
.) Est-il une raison que c'est une mauvaise idée?
- L'expression
x instanceof SomeClass
est faux six
estnull
. Par conséquent, la deuxième syntaxe se complique pas besoin de la valeur null est à vérifier. - Oui, le paragraphe immédiatement après l'extrait de code dit cela ainsi. C'est dans l'extrait de code parce que c'est ce que Eclipse génère.
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez
instanceof
, ce qui rend votreequals
mise en œuvrefinal
permettra de conserver la symétrie du contrat de la méthode:x.equals(y) == y.equals(x)
. Sifinal
semble restrictif, examinez soigneusement votre notion de l'objet d'équivalence assurez-vous que votre principale implémentations de maintenir intégralement le contrat établi par laObject
classe.final
semble restrictif" (sur les deuxequals
ethashCode
) puis utilisergetClass()
l'égalité au lieu deinstanceof
afin de préserver la symétrie et la transitivité des exigences de laequals
contrat.Josh Bloch favorise votre approche:
Voir aussi cette SORTE de réponse.
Efficace Java chapitre 3 couvre aussi cette.
getClass
ne viole pas le LSP, depuis le LSP simplement se rapporte à ce qui peut être fait avec les instances existantes--pas ce genre de cas peut être construit. La classe retournée pargetClass
est immuable la propriété d'une instance d'objet. Le LSP n'implique pas qu'il devrait être possible de créer une sous-classe lorsque cette propriété indique une autre catégorie que celle qui l'a créé.Angelika Langers Secrets d'égal à s'attire des ennuis avec une longue et détaillée pour quelques communes et les exemples bien connus, y compris par Josh Bloch et Barbara Liskov, la découverte d'un couple de problèmes dans la plupart d'entre eux. Elle a également fait dans la
instanceof
vsgetClass
. Certains n'en citerLa raison d'utiliser des
getClass
est d'assurer la propriété symétrique de laequals
contrat. D'égal à' la documentation Javadoc:En utilisant instanceof, il est possible de ne pas être symétrique. Prenons l'exemple:
Le chien s'étend de l'Animal.
Animal
equals
uninstanceof
contrôle de l'Animal.Chien
equals
uninstanceof
case du Chien.Donner des Animaux un et le Chien d (avec d'autres champs de la même):
Cela viole la propriété symétrique.
De suivre strictement l'égalité du contrat, la symétrie doit être assurée, et donc de la classe doit être la même.
a.equals(c)
etb.equals(c)
, puisa.equals(b)
(l'approche naïve de faireDog.equals
justereturn super.equals(object)
quand!(object instanceof Dog)
, mais vérifier les champs supplémentaires lorsque c'est un Chien instance ne serait pas en violation de la symétrie, mais serait en violation de transitivité)getClass()
contrôle d'égalité, ou vous pouvez utiliser uninstanceof
vérifier si faire de votreequals
ethashCode
méthodesfinal
.C'est quelque chose d'un débat religieux. Les deux approches ont leurs problèmes.
Bloch a un autre morceau de conseils en Efficace Java Deuxième Édition:
getClass
contreviendrait à la LSP, à moins que la classe de base documenté un moyen par lequel il devrait être possible de faire les instances des différentes sous-classes qui permettent de comparer l'égalité. Ce LSP violation voyez-vous?getClass()
ne doit pas être considérée comme significative au-delà du fait que la classe en question est convertible à la classe de base, le retour degetClass()
doit être considéré comme n'importe quel autre propriété qui doit correspondre pour les instances à l'égalité.final
.Corrigez-moi si je me trompe, mais getClass() sera utile lorsque vous voulez vous assurer que votre exemple n'est PAS une sous-classe de la classe que vous comparez avec les. Si vous utiliser instanceof dans cette situation, vous ne pouvez PAS le savoir car:
Si vous voulez vous assurer seulement que la classe correspondra alors utiliser
getClass() ==
. Si vous souhaitez faire correspondre les sous-classes puisinstanceof
est nécessaire.Aussi, instanceof ne correspondent pas à l'encontre d'un nul mais il est sûr à comparer à une valeur null. Si vous n'avez pas à null vérifier.
Cela dépend si vous considérez si une sous-classe d'une classe donnée est égale à celle de son parent.
ici, je voudrais utiliser "instanceof", parce que je veux un Nom d'être comparé à Nomdefamille
ici, je voudrais utiliser 'getClass", parce que la classe déjà dit que les deux instances ne sont pas équivalentes.
instanceof fonctionne pour les instences de la même classe ou ses sous-classes
ArryaList et RoleList sont à la fois instanceof Liste
Tout
getClass() == o.getClass() n'est vrai que si les deux objets ( ce et o ) appartient à la même classe.
Donc, en fonction de ce que vous avez besoin de comparer vous pouvez utiliser l'un ou l'autre.
Si votre logique est: "l'Un des objets est égale à d'autres que s'ils sont tous les deux de la même classe" vous devriez aller pour le "égaux", qui je pense est la plupart des cas.
Les deux méthodes ont leurs problèmes.
Si la sous-classe des modifications de l'identité, alors vous avez besoin de comparer leurs classes réelles. Sinon, vous violez la propriété symétrique. Par exemple, les différents types de
Person
s ne doivent pas être considérées comme équivalentes, même si elles ont le même nom.Cependant, certaines sous-classes ne changent pas d'identité, et il faut utiliser
instanceof
. Par exemple, si nous avons un tas de immuableShape
objets, puis unRectangle
avec la longueur et la largeur de 1 doit être égal à l'unitéSquare
.Dans la pratique, je pense que le premier cas est plus susceptible d'être vrai. Généralement, le sous-classement est une partie fondamentale de votre identité et d'être exactement comme votre parent, sauf que vous pouvez faire une petite chose ne vous rend pas égaux.
Fait instanceof vérifier si un objet appartient à une hiérarchie ou pas. ex: la Voiture, l'objet appartient à Vehical classe. Donc, "new Voiture() de l'instance de Vehical" renvoie la valeur true. Et "new Voiture().getClass().equals(Vehical.class)" return false, si la Voiture objet appartient à Vehical classe, mais il est classé comme un type distinct.