171 votes

Une raison à préférer les getClass() 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écochée et utiliser .getClass() pour comparer les types. Est-il une raison que je préférerais .getClass() sur instanceof?

Sans l'aide d' 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 l' 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?

173voto

Michael Myers Points 82361

Josh Bloch faveurs de votre démarche:

La raison pour laquelle j'en faveur de l' instanceof approche est que lorsque vous utilisez l' getClass approche, vous avez la restriction que les objets ne sont égaux à d'autres objets de la même classe, le même type de temps. Si vous étendre une classe et ajouter un couple de méthodes inoffensives, puis vérifier pour voir si un objet de la sous-classe est égale à un objet de la classe supérieure, même si les objets sont égaux dans tous les aspects importants, vous obtiendrez une réponse surprenante qu'ils ne sont pas égaux. En fait, il y a violation d'une interprétation stricte du principe de substitution de Liskov, et peut conduire à de très surprenant comportement. En Java, il est particulièrement important parce que la plupart des collections (HashTable, etc.) sont basés sur la méthode equals. Si vous mettez un membre de la super-classe dans une table de hachage de la clé et de le rechercher à l'aide d'une sous-classe de l'instance, vous ne le trouverez pas, parce qu'ils ne sont pas égaux.

Voir aussi cette SORTE de réponse.

Efficace Java chapitre 3 couvre également cette.

97voto

erickson Points 127945

Si vous utilisez , rendant votre application préservera le contrat de symétrie de la méthode : . Si semble restrictif, soigneusement examiner votre notion d’équivalence de l’objet pour s’assurer que vos implémentations dominante maintiennent parfaitement le contrat établi par le classe.

64voto

Angelika Langers Secrets d'égal à é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 est également dans l' instanceof vs getClass. Quelques citations

Conclusions

Après avoir disséqué les quatre arbitrairement choisi des exemples de mises en œuvre de equals() , que faisons-nous en conclure?

Tout d'abord: il y a deux substantiellement différentes façons d'effectuer la vérification pour le type de match dans une mise en œuvre de equals() . Une classe peut permettre mixte-type de comparaison entre les super - et la sous-classe d'objets à l'aide de l'opérateur instanceof, ou une classe peut traiter des objets de type différent que la non-égalité par le biais de la getClass() de test. Les exemples ci-dessus illustre bien que les implémentations de equals() à l'aide de getClass() sont généralement plus robustes que ceux des implémentations à l'aide de instanceof .

Le instanceof test est correct uniquement pour la finale de classes ou si au moins la méthode equals() est définitive dans une super-classe. Le dernier essentiellement implique qu'aucune sous-classe doit étendre la classe mère de l'etat, mais peut seulement ajouter des fonctionnalités ou des champs qui ne sont pas pertinents pour l'état de l'objet et du comportement, comme transitoires ou des champs statiques.

Les implémentations à l'aide de la getClass() test sur l'autre main toujours se conformer à la equals() contrat; ils sont corrects et robuste. Cependant, ils sont sémantiquement très différentes implémentations utiliser le instanceof test. Implémentations utilisant getClass() ne permet pas la comparaison des sous - avec de la super-classe des objets, pas même lorsque le sous-classe ne pas ajouter de champs et ne serait même pas de vouloir remplacer equals() . Tel un "trivial" extension de classe serait, par exemple, l'ajout d'un debug-méthode d'impression dans une sous-classe définie pour exactement ce "trivial" but. Si la superclasse interdit mixte-type de comparaison via le getClass (), puis le trivial extension ne serait pas comparable à sa super-classe. Si oui ou non il s'agit d'un problème dépend entièrement de la sémantique de la classe et le but de l'extension.

58voto

Steve Kuo Points 15196

La raison de l'utilisation d' getClass est d'assurer la propriété symétrique de l' equals contrat. D'égal à' la documentation Javadoc:

Elle est symétrique: pour toute non-null les valeurs de référence x et y, x.equals(y) doit retourner true si et seulement si y.est égal à(x) renvoie la valeur true.

En utilisant instanceof, il est possible de ne pas être symétrique. Prenons l'exemple: Le chien s'étend de l'Animal. Animal equals un instanceof contrôle de l'Animal. Chien equals un instanceof case du Chien. Donner à l'Animal un Chien et d (avec d'autres champs de la même):

a.equals(d) --> true
d.equals(a) --> false

Cela est une violation de la propriété symétrique.

Suivre strictement égal du contrat, la symétrie doit être assurée, et donc de la classe doit être la même.

26voto

McDowell Points 62645

C'est quelque chose d'un débat religieux. Les deux approches ont leurs problèmes.

  • Utiliser instanceof et vous ne pouvez pas ajouter beaucoup de membres de sous-classes.
  • Utilisation getClass et vous violer le principe de substitution de Liskov.

Bloch a un autre morceau de conseils Efficaces Java Deuxième Édition:

  • Article 17: la Conception et le document de l'héritage ou de l'interdire

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X