1. Comparer des objets en Java
En Java, les objets peuvent être comparés à la fois par référence et par valeur.
Comparer des références
Si deux variables pointent vers le même objet en mémoire, alors les références stockées dans ces variables sont égales. Si vous comparez ces variables à l'aide de l'opérateur d'égalité ( ==), vous obtenez vrai et ce résultat est logique. Tout est simple ici.
| Code | Sortie console |
|---|---|
|
|
Comparer par valeur
Mais vous pouvez souvent rencontrer des situations où deux variables font référence à deux objets distincts qui sont identiques. Par exemple, deux objets chaînes différents qui contiennent le même texte.
Pour déterminer si différents objets sont identiques, utilisez la equals()méthode. Par exemple:
| Code | Sortie console |
|---|---|
|
|
La equalsméthode n'est pas limitée à la Stringclasse. Chaque classe en a.
Même les cours que vous écrivez vous-même, et voici pourquoi.
2. Objectclasse
Toutes les classes en Java héritent de la Objectclasse. Les créateurs de Java ont proposé cette approche.
Et si une classe hérite de la Objectclasse, alors elle gagne toutes les méthodes de la Objectclasse. Et c'est une conséquence majeure de l'héritage.
En d'autres termes, chaque classe possède les méthodes de la Objectclasse, même si leur code ne les mentionne pas.
Ces méthodes héritées incluent des méthodes liées à la comparaison d'objets. Ce sont les méthodes equals()et hashCode().
| Code | En réalité, voici ce que nous aurons : |
|---|---|
|
|
Dans l'exemple ci-dessus, nous avons créé une classe simple Personavec des paramètres de nom et d'âge, mais pas une seule méthode. Mais comme toutes les classes héritent de la Objectclasse, la Personclasse a automatiquement deux méthodes :
| Méthode | Description |
|---|---|
|
Compare l'objet courant et l'objet passé |
|
Renvoie le hashcode de l'objet courant |
Il s'avère qu'absolument chaque objet a la equalsméthode, et des objets de différents types peuvent être comparés les uns aux autres. Un tel code se compilera et fonctionnera parfaitement.
| Code | Sortie console |
|---|---|
|
|
|
|
3. equals()méthode
La equals()méthode, héritée de la Objectclasse, implémente l'algorithme le plus simple pour comparer l'objet courant avec les objets passés : elle compare simplement les références aux objets.
Vous obtenez le même résultat si vous comparez simplement Persondes variables au lieu d'appeler la equals()méthode. Exemple:
| Code | Sortie console |
|---|---|
|
|
Lorsque la equalsméthode est appelée sur a, elle compare simplement la référence stockée dans la avariable avec la référence stockée dans la bvariable.
Cependant, la comparaison fonctionne différemment pour la Stringclasse. Pourquoi?
Parce que les gens qui ont créé la Stringclasse ont écrit leur propre implémentation de la equals()méthode.
Mise en œuvre de la equals()méthode
Écrivons maintenant notre propre implémentation de la méthode equals dans la Personclasse. Nous allons considérer 4 cas principaux.
equalsméthode, elle prend toujours un
Objectobjet comme argument
Scénario 1 : le même objet sur lequel la equalsméthode est appelée est également passé à la equalsméthode. Si les références de l'objet courant et de l'objet passé sont égales, la méthode doit retourner true. Un objet est égal à lui-même.
Dans le code, cela ressemblera à ceci :
| Code | Description |
|---|---|
|
Comparer les références |
Scénario 2 : nullest passé à la equalsméthode — nous n'avons rien à comparer. L'objet sur lequel la equalsméthode est appelée n'est certainement pas nul, nous devons donc revenir falsedans ce cas.
Dans le code, cela ressemblera à ceci :
| Code | Description |
|---|---|
|
Comparer les références L'objet passé est-il null? |
Scénario 3 : une référence à un objet qui n'est pas a Personest passée à la equalsméthode. L' Personobjet est-il égal au non- Personobjet ? C'est une question pour le développeur de la Personclasse de décider comme il le souhaite.
Mais généralement, les objets doivent appartenir à la même classe pour être considérés comme égaux. Par conséquent, si quelque chose d'autre qu'un objet de la Personclasse est passé à notre méthode equals, alors nous retournerons toujours false. Comment vérifier le type d'un objet ? C'est vrai — en utilisant l' instanceofopérateur.
Voici à quoi ressemble notre nouveau code :
| Code | Description |
|---|---|
|
Comparer les références L'objet passé est-il null? Si l'objet passé n'est pas un Person |
4. Comparer deux Personobjets
Avec quoi avons-nous fini? Si nous avons atteint la fin de la méthode, alors nous avons une Personréférence d'objet qui n'est pas null. Nous le convertissons donc en a Personet comparons les données internes pertinentes des deux objets. Et c'est notre quatrième scénario .
| Code | Description |
|---|---|
|
Comparer les références L'objet passé est-il null? Si l'objet passé n'est pas un Person Typecasting |
Et comment comparer deux Personobjets ? Ils sont égaux s'ils ont le même nom ( name) et le même âge ( age). Le code final ressemblera à ceci :
| Code | Description |
|---|---|
|
Comparer les références L'objet passé est-il null? Si l'objet passé n'est pas un Person Typecasting |
Mais ce n'est pas tout.
Tout d'abord, le champ de nom est un String, vous devez donc comparer le champ de nom en appelant la equalsméthode.
this.name.equals(person.name)
Deuxièmement, le namechamp peut être null: dans ce cas, vous ne pouvez pas equalsl'appeler. Vous avez besoin d'un chèque supplémentaire pour null:
this.name != null && this.name.equals(person.name)
Cela dit, si le champ de nom se trouve nulldans les deux Personobjets, les noms sont toujours égaux.
Le code du quatrième scénario pourrait ressembler à ceci :
|
Si les âges ne sont pas égaux, immédiatement return false Si this.nameest égal à null, il n'y a pas lieu de comparer avec la equalsméthode. Ici, soit le deuxième namechamp est égal à null, soit il ne l'est pas. Comparez les deux champs de nom à l'aide de la equalsméthode. |
5. hashCode()méthode
En plus de la equalsméthode qui a pour but d'effectuer une comparaison détaillée de tous les champs des deux objets, il existe une autre méthode qui peut être utilisée pour une comparaison imprécise mais très rapide : hashCode().
Imaginez que vous triez par ordre alphabétique une liste de milliers de mots et que vous devez comparer à plusieurs reprises des paires de mots. Et les mots sont longs, composés de beaucoup de lettres. D'une manière générale, une telle comparaison prendrait beaucoup de temps.
Mais cela peut être accéléré. Supposons que nous ayons des mots qui commencent par des lettres différentes - il est immédiatement clair qu'ils sont différents. Mais s'ils commencent par les mêmes lettres, nous ne pouvons pas encore dire quel sera le résultat : les mots peuvent s'avérer égaux ou différents.
La hashCode()méthode fonctionne selon un principe similaire. Si vous l'appelez sur un objet, il renvoie un certain nombre - analogue à la première lettre d'un mot. Ce nombre a les propriétés suivantes :
- Des objets identiques ont toujours le même hashcode
- Différents objets peuvent avoir le même hashcode, ou leurs hashcodes peuvent être différents
- Si les objets ont des hashcodes différents, alors les objets sont définitivement différents
Pour rendre cela encore plus clair, recadrons ces propriétés en termes de mots :
- Des mots identiques ont toujours les mêmes premières lettres.
- Différents mots peuvent avoir les mêmes premières lettres, ou leurs premières lettres peuvent être différentes
- Si les mots ont des premières lettres différentes, alors les mots sont définitivement différents
La dernière propriété est utilisée pour accélérer la comparaison des objets :
Tout d'abord, les hashcodes des deux objets sont calculés. Si ces hashcodes sont différents, alors les objets sont définitivement différents et il n'est pas nécessaire de les comparer davantage.
Mais si les hashcodes sont les mêmes, nous devons encore comparer les objets en utilisant la méthode equals.
6. Contrats en code
Le comportement décrit ci-dessus doit être implémenté par toutes les classes en Java. Lors de la compilation, il n'existe aucun moyen de vérifier si les objets sont correctement comparés.
Les programmeurs Java ont un accord universel sur le fait que s'ils écrivent leur propre implémentation de la méthode equals () et remplacent ainsi l'implémentation standard (dans la Objectclasse), ils doivent également écrire leur propre implémentation de la hashCode()méthode de manière à ce que les règles susmentionnées soient satisfait.
Cet arrangement s'appelle un contrat .
Si vous implémentez uniquement la equals()ou uniquement la hashCode()méthode dans votre classe, vous êtes en violation flagrante du contrat (vous avez rompu l'accord). Ne fais pas ça.
Si d'autres programmeurs utilisent votre code, il se peut qu'il ne fonctionne pas correctement. De plus, vous utiliserez un code qui repose sur le respect des contrats ci-dessus.
Lors de la recherche d'un élément, toutes les collections Java comparent d'abord les codes de hachage des objets, puis effectuent ensuite une comparaison à l'aide de la equalsméthode.
Cela signifie que si vous donnez une equalsméthode à votre propre classe mais que vous n'écrivez pas votre propre hashCode()méthode ou que vous l'implémentez de manière incorrecte, les collections peuvent ne pas fonctionner correctement avec vos objets.
Par exemple, vous pouvez ajouter un objet à une liste, puis le rechercher à l'aide de la contains()méthode, mais la collection risque de ne pas trouver votre objet.
GO TO FULL VERSION