Maison >Java >javaDidacticiel >Présentation des méthodes plus approfondies de remplacement des égaux en Java

Présentation des méthodes plus approfondies de remplacement des égaux en Java

Y2J
Y2Joriginal
2017-04-24 16:07:411344parcourir

J'ai récemment parlé avec mes collègues de la différence entre égaux et ==. Il s'agit en fait d'une question très ancienne et simple, mais lorsque vous souhaitez remplacer vous-même la méthode égale, vous constatez qu'il y a certaines choses que vous ne savez pas mais que vous devez savoir. Couvrir les égaux demande beaucoup d’attention. Bien que Object soit une classe très spécifique, son rôle principal est d’étendre. Toutes ses méthodes non finales ont des conventions générales claires. Parce qu'ils sont conçus pour être des méthodes remplacées. Toute classe qui remplace equals, hashCode, toString, clone et finalize est responsable du respect des conventions générales de ces méthodes. Si cela n’est pas possible, il sera difficile d’obtenir l’effet souhaité lorsque plusieurs classes sont combinées.

Ne remplacez pas la méthode égale


Remplacer la méthode égale semble simple, mais il existe de nombreuses méthodes de substitution qui peuvent provoquer des erreurs. Le moyen le plus simple d'éviter cette erreur est de ne pas remplacer les égaux, auquel cas chaque instance de classe n'est égale qu'à elle-même. Alors, dans quelles circonstances pouvons-nous choisir de ne pas remplacer la méthode des égalités ?

Chaque instance d'une classe est intrinsèquement unique

Cela est vrai pour les classes qui représentent des entités actives plutôt que des valeurs, comme chaque instance de thread. Cela n’a aucun sens pour nous de le comparer avec la méthode égale, car chaque thread est unique. Dans ce cas, nous n'avons pas besoin de remplacer la méthode equals, car la méthode equals de la classe Object est tout à fait suffisante.

Implémentation de la méthode égale dans la classe Objet :

 public boolean equals(Object obj) { return (this == obj);  }

Peu importe si la classe nécessite un jugement d'égalité logique

Certaines classes sont des "classes numériques". La comparaison des tailles et les opérations mathématiques sont le travail de ces classes. Dans ce cas, nous devons comparer les valeurs stockées dans la classe et porter un jugement d'égalité logique. En dehors de cela, la plupart des classes n'ont pas la notion de « si l'un est égal à l'autre ». Les classes qui ne se soucient pas de l’égalité logique n’ont pas besoin de remplacer la méthode equals.

L'égal implémenté par la super classe est applicable aux sous-classes

Par exemple, il n'y a aucune différence dans la méthode égale de la classe HashSet qui hérite de la classe AbstractSet, puis HashSet directement. Utilisez simplement la méthode égale de AbstractSet.

Remplacer la méthode égale

Contrairement à ce qui précède, la situation dans laquelle nous devons remplacer la méthode égale est la suivante : si la classe a son propre concept d'égalité logique, et la classe parent. Il n'y a pas de substitution de méthode égale disponible. À ce stade, nous devons le couvrir nous-mêmes.

La relation d'équivalence de la méthode égale dans la collection


La méthode égale implémente la relation d'équivalence. J'ai appris le concept de relations d'équivalence en mathématiques discrètes. Pour une relation binaire sur R, si elle satisfait la symétrie spontanée et la transitivité, alors elle est équivalente. Analysons en détail la relation entre les égaux et ces trois propriétés.

Réflexivité : Pour toute valeur de référence non nulle x, x.equals(x) doit renvoyer true

Symétrie : Pour toute valeur non nulle -valeurs de référence nulles x et y, si et seulement si y.equals(x) renvoie vrai, x.equals(y) doit renvoyer vrai

Transitivité : Pour tout Pour non -valeurs de référence nulles x, y et z, si x.equals(y) renvoie vrai et y.equals(z) renvoie également vrai, alors x.equals(z) doit renvoyer vrai.

Réflexivité : ∀ a ∈A, => (a, a) ∈ R
Symétrie : (a, b) ∈R∧ a ≠ b => 🎜> Transitivité : (a, b)∈R, (b, c)∈R => (a, c)∈R

En comparant ces trois propriétés, il n'y a pas de problème. On peut voir que la méthode égale réalise la relation d’équivalence.

Comment écrire la méthode égale


La méthode égale de Object regarde simplement l'adresse, ce qui est évidemment impossible de répondre à nos exigences. Alors, comment pouvons-nous garantir que nous écrivons une méthode de comparaison logique et de haute qualité lorsque nous écrivons nous-mêmes la méthode égale ? L'écriture d'égaux peut être résumée dans les quatre étapes suivantes :

1. Utilisez l'opérateur == pour vérifier si le paramètre est simplement une référence à l'objet Si les résultats sont égaux, renvoient vrai, indiquant que x et y sont des références différentes à un objet et aucun jugement supplémentaire n'est nécessaire.

2. Utilisez l'opérateur instanceof pour vérifier si le type du paramètre est correct Si le résultat n'est pas du type correct, renvoyez false, car notre méthode égale hérite de l'objet. classe, donc les paramètres Le type inévitable est Object.Nous utilisons d'abord instanceof pour juger du type des paramètres. Si les types ne sont pas corrects, il n'est pas nécessaire de passer à l'étape suivante de jugement.

3. Convertissez les paramètres dans le type correct Étant donné que la détection a été effectuée auparavant, il n'y a aucun problème avec la conversion de type dans cette étape.

4. Jugez les valeurs de domaine qui doivent être logiquement comparées dans chaque classe Après vous être assuré que x et y sont des instances différentes du même type, déterminez les champs qui doit être comparé logiquement. La valeur peut être extraite à des fins de comparaison et de jugement. Renvoie vrai si tout est correct, faux sinon.

Choses à noter sur l'implémentation d'égal


Après avoir écrit la méthode d'égalité, vous devez juger à plusieurs reprises si elle est conforme à la réflexivité, à la symétrie et à la transitivité. Non seulement cela, mais il y a certaines choses à noter lors de l'écriture de la méthode égale tout en garantissant l'égalité, et nous devons améliorer cela.

Toujours remplacer la méthode hashCode lors du remplacement de la méthode égal
Si nous écrivons une classe liée au hachage, nous devons remplacer la méthode hashCode lors du remplacement de la méthode égale. Car dans une table de hachage, les objets logiquement identiques doivent avoir le même code de hachage. Pour donner un exemple relativement simple : stockez une chaîne dans un HashSet. Il est possible que deux chaînes String avec le même contenu soient jugées fausses en utilisant ==, mais une seule copie d'entre elles existe dans le HashSet. En effet, les chaînes ayant la même logique ont le même hashCode.
En général, si vous remplacez la méthode equals pour votre classe, cela prouve que deux objets différents sont logiquement égaux dans certaines circonstances. Si cela est lié au hachage à ce moment-là, alors les deux objets ont besoin du même hashCode. Par conséquent, lorsque vous remplacez la méthode equals, remplacez toujours la méthode hashCode.

Ne rendez pas la méthode égale trop intelligente
Si nous suivons simplement le processus d'implémentation ci-dessus pour écrire la méthode égale, elle sera conforme à la réglementation et ne provoquera pas d'erreurs étranges . Mais si nous insistons sur la poursuite de relations d'équivalence diverses et fantaisistes et rendons le code gonflé, cela violera non seulement l'intention initiale d'une cohésion élevée, mais provoquera également des erreurs inexplicables dans le code.

Ne vous méprenez pas sur le type de paramètre de la méthode égale
Cela peut sembler drôle de le dire, mais c'est ce qui se passe. Après avoir modifié le type du paramètre, la méthode equals n'a rien à voir avec la classe Object. Le compilateur ne signalera pas d'erreur, ne laissant que des maux de tête sans fin aux programmeurs. Si vous ne réalisez pas que le type du paramètre est Object, vous pouvez probablement passer des heures à vous demander pourquoi votre programme ne fonctionne pas correctement.

J'ai récemment parlé avec mes collègues de la différence entre égaux et ==. Il s'agit en fait d'une question très ancienne et simple, mais lorsque vous souhaitez remplacer vous-même la méthode égale, vous constatez qu'il y a certaines choses que vous ne savez pas mais que vous devez savoir. Couvrir les égaux demande beaucoup d’attention. Bien que Object soit une classe très spécifique, son objectif principal est d’étendre. Toutes ses méthodes non finales ont des conventions générales claires. Parce qu'ils sont conçus pour être des méthodes remplacées. Toute classe qui remplace equals, hashCode, toString, clone et finalize est responsable du respect des conventions générales de ces méthodes. Si cela n’est pas possible, il sera difficile d’obtenir l’effet souhaité lorsque plusieurs classes sont combinées.

Ne remplacez pas la méthode égale


Remplacer la méthode égale semble simple, mais il existe de nombreuses méthodes de substitution qui peuvent provoquer des erreurs. Le moyen le plus simple d'éviter cette erreur est de ne pas remplacer les égaux, auquel cas chaque instance de classe ne sera égale qu'à elle-même. Alors, dans quelles circonstances pouvons-nous choisir de ne pas remplacer la méthode des égalités ?

Chaque instance d'une classe est intrinsèquement unique

Cela est vrai pour les classes qui représentent des entités actives plutôt que des valeurs, comme chaque instance de thread. Cela n’a aucun sens pour nous de le comparer avec la méthode égale, car chaque thread est unique. Dans ce cas, nous n'avons pas besoin de remplacer la méthode equals, car la méthode equals de la classe Object est tout à fait suffisante.

Implémentation de la méthode égale dans la classe Objet :

 public boolean equals(Object obj) { return (this == obj);  }

Peu importe si la classe nécessite un jugement d'égalité logique

Certaines classes sont des "classes numériques". La comparaison des tailles et les opérations mathématiques sont le travail de ces classes. Dans ce cas, nous devons comparer les valeurs stockées dans la classe et porter un jugement d'égalité logique. En dehors de cela, la plupart des classes n'ont pas la notion de « si l'un est égal à l'autre ». Les classes qui ne se soucient pas de l’égalité logique n’ont pas besoin de remplacer la méthode equals.

L'égal implémenté par la super classe est applicable aux sous-classes

Par exemple, il n'y a aucune différence dans la méthode égale de la classe HashSet qui hérite de la classe AbstractSet, puis HashSet directement. Utilisez simplement la méthode égale de AbstractSet.

Remplacer la méthode égale

Contrairement à ce qui précède, la situation dans laquelle nous devons remplacer la méthode égale est la suivante : si la classe a son propre concept d'égalité logique, et la classe parent. Il n'y a pas de substitution de méthode égale disponible. À ce stade, nous devons le couvrir nous-mêmes.

La relation d'équivalence de la méthode égale dans la collection


La méthode égale implémente la relation d'équivalence. J'ai appris le concept de relations d'équivalence en mathématiques discrètes. Pour une relation binaire sur R, si elle satisfait la symétrie spontanée et la transitivité, alors elle est équivalente. Analysons en détail la relation entre les égaux et ces trois propriétés.

Réflexivité : Pour toute valeur de référence non nulle x, x.equals(x) doit renvoyer true

Symétrie : Pour toute valeur non nulle -valeurs de référence nulles x et y, si et seulement si y.equals(x) renvoie vrai, x.equals(y) doit renvoyer vrai

Transitivité : Pour tout Pour non -valeurs de référence nulles x, y et z, si x.equals(y) renvoie vrai et y.equals(z) renvoie également vrai, alors x.equals(z) doit renvoyer vrai.

Réflexivité : ∀ a ∈A, => (a, a) ∈ R
Symétrie : (a, b) ∈R∧ a ≠ b => 🎜> Transitivité : (a, b)∈R, (b, c)∈R => (a, c)∈R

En comparant ces trois propriétés, il n'y a pas de problème. On peut voir que la méthode égale réalise la relation d’équivalence.

Comment écrire la méthode égale


La méthode égale de Object regarde simplement l'adresse, ce qui est évidemment impossible de répondre à nos exigences. Alors, comment pouvons-nous garantir que nous écrivons une méthode de comparaison logique et de haute qualité lorsque nous écrivons nous-mêmes la méthode égale ? L'écriture d'égaux peut être résumée dans les quatre étapes suivantes :

1. Utilisez l'opérateur == pour vérifier si le paramètre est simplement une référence à l'objet Si les résultats sont égaux, renvoient vrai, indiquant que x et y sont des références différentes à un objet et aucun jugement supplémentaire n'est nécessaire.

2. Utilisez l'opérateur instanceof pour vérifier si le type du paramètre est correct Si le résultat n'est pas du type correct, renvoyez false, car notre méthode égale hérite de l'objet. classe, donc les paramètres Le type inévitable est Object.Nous utilisons d'abord instanceof pour juger du type des paramètres. Si les types ne sont pas corrects, il n'est pas nécessaire de passer à l'étape suivante de jugement.

3. Convertissez les paramètres dans le type correct Étant donné que la détection a été effectuée auparavant, il n'y a aucun problème avec la conversion de type dans cette étape.

4. Jugez les valeurs de domaine qui doivent être logiquement comparées dans chaque classe Après vous être assuré que x et y sont des instances différentes du même type, déterminez les champs qui doit être comparé logiquement. La valeur peut être extraite à des fins de comparaison et de jugement. Renvoie vrai si tout est correct, faux sinon.

Choses à noter sur l'implémentation d'égal


Après avoir écrit la méthode d'égalité, vous devez juger à plusieurs reprises si elle est conforme à la réflexivité, à la symétrie et à la transitivité. Non seulement cela, mais il y a certaines choses à noter lors de l'écriture de la méthode égale tout en garantissant l'égalité, et nous devons améliorer cela.

Toujours remplacer la méthode hashCode lors du remplacement de la méthode égal
Si nous écrivons une classe liée au hachage, nous devons remplacer la méthode hashCode lors du remplacement de la méthode égale. Car dans une table de hachage, les objets logiquement identiques doivent avoir le même code de hachage. Pour donner un exemple relativement simple : stockez une chaîne dans un HashSet. Il est possible que deux chaînes String avec le même contenu soient jugées fausses en utilisant ==, mais une seule copie d'entre elles existe dans le HashSet. En effet, les chaînes ayant la même logique ont le même hashCode.
En général, si vous remplacez la méthode equals pour votre classe, cela prouve que deux objets différents sont logiquement égaux dans certaines circonstances. Si cela est lié au hachage à ce moment-là, alors les deux objets ont besoin du même hashCode. Par conséquent, lorsque vous remplacez la méthode equals, remplacez toujours la méthode hashCode.

Ne rendez pas la méthode égale trop intelligente
Si nous suivons simplement le processus d'implémentation ci-dessus pour écrire la méthode égale, elle sera conforme à la réglementation et ne provoquera pas d'erreurs étranges . Mais si nous insistons sur la poursuite de relations d'équivalence diverses et fantaisistes et rendons le code gonflé, cela violera non seulement l'intention initiale d'une cohésion élevée, mais provoquera également des erreurs inexplicables dans le code.

Ne vous méprenez pas sur le type de paramètre de la méthode égale
Cela peut sembler drôle de le dire, mais c'est ce qui se passe. Après avoir modifié le type du paramètre, la méthode equals n'a rien à voir avec la classe Object. Le compilateur ne signalera pas d'erreur, ne laissant que des maux de tête sans fin aux programmeurs. Si vous ne réalisez pas que le type du paramètre est Object, vous pouvez probablement passer des heures à vous demander pourquoi votre programme ne fonctionne pas correctement.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn