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 equals
méthode n'est pas limitée à la String
classe. Chaque classe en a.
Même les cours que vous écrivez vous-même, et voici pourquoi.
2. Object
classe
Toutes les classes en Java héritent de la Object
classe. Les créateurs de Java ont proposé cette approche.
Et si une classe hérite de la Object
classe, alors elle gagne toutes les méthodes de la Object
classe. Et c'est une conséquence majeure de l'héritage.
En d'autres termes, chaque classe possède les méthodes de la Object
classe, 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 Person
avec des paramètres de nom et d'âge, mais pas une seule méthode. Mais comme toutes les classes héritent de la Object
classe, la Person
classe 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 equals
mé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 Object
classe, 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 Person
des variables au lieu d'appeler la equals()
méthode. Exemple:
Code | Sortie console |
---|---|
|
|
Lorsque la equals
méthode est appelée sur a
, elle compare simplement la référence stockée dans la a
variable avec la référence stockée dans la b
variable.
Cependant, la comparaison fonctionne différemment pour la String
classe. Pourquoi?
Parce que les gens qui ont créé la String
classe 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 Person
classe. Nous allons considérer 4 cas principaux.
equals
méthode, elle prend toujours un Object
objet comme argument
Scénario 1 : le même objet sur lequel la equals
méthode est appelée est également passé à la equals
mé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 : null
est passé à la equals
méthode — nous n'avons rien à comparer. L'objet sur lequel la equals
méthode est appelée n'est certainement pas nul, nous devons donc revenir false
dans 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 Person
est passée à la equals
méthode. L' Person
objet est-il égal au non- Person
objet ? C'est une question pour le développeur de la Person
classe 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 Person
classe 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' instanceof
opé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 Person
objets
Avec quoi avons-nous fini? Si nous avons atteint la fin de la méthode, alors nous avons une Person
référence d'objet qui n'est pas null
. Nous le convertissons donc en a Person
et 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 Person
objets ? 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 equals
méthode.
this.name.equals(person.name)
Deuxièmement, le name
champ peut être null
: dans ce cas, vous ne pouvez pas equals
l'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 null
dans les deux Person
objets, 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.name est égal à null , il n'y a pas lieu de comparer avec la equals méthode. Ici, soit le deuxième name champ est égal à null , soit il ne l'est pas. Comparez les deux champs de nom à l'aide de la equals méthode. |
5. hashCode()
méthode
En plus de la equals
mé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 Object
classe), 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 equals
méthode.
Cela signifie que si vous donnez une equals
mé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