Quelle est la différence entre ==
et .equals()
dans Scala, et quand utiliser lequel?
L'implémentation est-elle la même qu'en Java?
EDIT: La question connexe parle de cas spécifiques de AnyVal
. Le cas le plus général est Any
.
Quelle est la différence entre ==
et .equals()
dans Scala, et quand utiliser lequel?
L'implémentation est-elle la même qu'en Java?
EDIT: La question connexe parle de cas spécifiques de AnyVal
. Le cas le plus général est Any
.
Réponses:
Vous utilisez normalement
==
, il achemine versequals
, sauf qu'il traitenull
s correctement. L'égalité de référence (rarement utilisée) esteq
.la source
3 == BigInt(3)
etBigInt(3) == 3
sont vrais. Mais,3.equals(BigInt(3))
est faux, alors queBigInt(3).equals(3)
c'est vrai. Par conséquent, préférez utiliser==
. Évitez d'utiliserequals()
dans scala. Je pense==
que la conversion implicite bien, maisequals()
pas.new java.lang.Integer(1) == new java.lang.Double(1.0)
est-ce vrai alors quenew java.lang.Integer(1) equals new java.lang.Double(1.0)
c'est faux?==
est une méthode finale, et appelle.equals
, qui n'est pas définitive.Ceci est radicalement différent de Java, où
==
est un opérateur plutôt qu'une méthode et compare strictement l'égalité de référence pour les objets.la source
TL; DR
equals
méthode pour comparer le contenu de chaque instance. C'est la mêmeequals
méthode utilisée en Java==
opérateur pour comparer, sans vous soucier desnull
référenceseq
méthode pour vérifier si les deux arguments sont exactement la même référence. Il est recommandé de ne pas utiliser à moins que vous ne compreniez comment cela fonctionne et fonctionnera souventequals
pour ce dont vous avez besoin à la place. Et assurez-vous de ne l'utiliser qu'avec desAnyRef
arguments, pas seulementAny
REMARQUE: dans le cas de
equals
, tout comme en Java, il peut ne pas renvoyer le même résultat si vous changez d'arguments, par exemple1.equals(BigInt(1))
retournerafalse
là où l'inverse retourneratrue
. Cela est dû au fait que chaque implémentation ne vérifie que des types spécifiques. Les nombres primitifs ne vérifient pas si le deuxième argument est de typesNumber
niBigInt
mais uniquement d'autres types primitifsDétails
La
AnyRef.equals(Any)
méthode est celle remplacée par les sous-classes. Une méthode de la spécification Java qui est également venue à Scala. S'il est utilisé sur une instance sans boîte, il est encadré pour l'appeler (bien que caché dans Scala; plus évident en Java avecint
->Integer
). L'implémentation par défaut compare simplement les références (comme en Java)La
Any.==(Any)
méthode compare deux objets et autorise l'un ou l'autre des arguments à être nul (comme pour appeler une méthode statique avec deux instances). Il compare si les deux sontnull
, puis il appelle laequals(Any)
méthode sur une instance encadrée.La
AnyRef.eq(AnyRef)
méthode compare uniquement les références, c'est-à-dire l'emplacement de l'instance en mémoire. Il n'y a pas de boxe implicite pour cette méthode.Exemples
1 equals 2
reviendrafalse
, car il redirige versInteger.equals(...)
1 == 2
reviendrafalse
, car il redirige versInteger.equals(...)
1 eq 2
ne compilera pas, car les deux arguments doivent être de typeAnyRef
new ArrayList() equals new ArrayList()
reviendratrue
, car il vérifie le contenunew ArrayList() == new ArrayList()
reviendratrue
, car il redirige versequals(...)
new ArrayList() eq new ArrayList()
retournerafalse
, car les deux arguments sont des instances différentesfoo equals foo
sera de retourtrue
, à moinsfoo
estnull
, puis va lancer uneNullPointerException
foo == foo
sera de retourtrue
, même sifoo
estnull
foo eq foo
retourneratrue
, puisque les deux arguments sont liés à la même référencela source
Il existe une différence intéressante entre
==
etequals
pourFloat
et lesDouble
types: Ils traitentNaN
différemment:Edit: Comme cela a été souligné dans un commentaire - "cela se produit également en Java" - dépend de ce que c'est exactement :
Cela imprimera
Donc, les
unboxedNan
rendementsfalse
comparés pour l'égalité parce que c'est ainsi que les nombres à virgule flottante IEEE le définissent et cela devrait vraiment se produire dans chaque langage de programmation (bien que cela perturbe en quelque sorte la notion d'identité).Le NaN encadré donne vrai pour la comparaison utilisant
==
en Java pendant que nous comparons les références d'objet.Je n'ai pas d'explication pour le
equals
cas,==
à mon humble avis , il devrait vraiment se comporter de la même manière que sur les valeurs doubles sans boîte, mais ce n'est pas le cas.Traduit en Scala, la question est un peu plus compliquée car Scala a unifié les types primitifs et objets en
Any
et se traduit par le double primitif et le double encadré si nécessaire. Ainsi, la scala==
se résume apparemment à une comparaison deNaN
valeurs primitives maisequals
utilise celle définie sur les valeurs Double encadrées (il y a beaucoup de magie de conversion implicite en cours et il y a des choses qui sont pimpées sur des doublesRichDouble
).Si vous avez vraiment besoin de savoir si quelque chose est réellement
NaN
utiliséisNaN
:la source
Dans Scala == vérifiez d'abord les valeurs Null , puis appelle la méthode equals sur le premier objet
la source