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 vers equals, sauf qu'il traite nulls correctement. L'égalité de référence (rarement utilisée) est eq.
3 == BigInt(3)et BigInt(3) == 3sont vrais. Mais, 3.equals(BigInt(3))est faux, alors que BigInt(3).equals(3)c'est vrai. Par conséquent, préférez utiliser ==. Évitez d'utiliser equals()dans scala. Je pense ==que la conversion implicite bien, mais equals()pas.
new java.lang.Integer(1) == new java.lang.Double(1.0)est-ce vrai alors que new java.lang.Integer(1) equals new java.lang.Double(1.0)c'est faux?
equalsméthode pour comparer le contenu de chaque instance. C'est la même equalsméthode utilisée en Java==opérateur pour comparer, sans vous soucier des nullréférenceseqmé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 souvent equalspour ce dont vous avez besoin à la place. Et assurez-vous de ne l'utiliser qu'avec des AnyRefarguments, pas seulementAnyREMARQUE: 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 exemple 1.equals(BigInt(1))retournera falselà où l'inverse retournera true. 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 types Numberni BigIntmais uniquement d'autres types primitifs
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 avec int-> 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 sont null, puis il appelle la equals(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.
1 equals 2reviendra false, car il redirige versInteger.equals(...)1 == 2reviendra false, car il redirige versInteger.equals(...)1 eq 2 ne compilera pas, car les deux arguments doivent être de type AnyRefnew ArrayList() equals new ArrayList()reviendra true, car il vérifie le contenunew ArrayList() == new ArrayList()reviendra true, car il redirige versequals(...)new ArrayList() eq new ArrayList()retournera false, car les deux arguments sont des instances différentesfoo equals foosera de retour true, à moins fooest null, puis va lancer uneNullPointerExceptionfoo == foosera de retour true, même si fooestnullfoo eq fooretournera true, puisque les deux arguments sont liés à la même référenceIl existe une différence intéressante entre ==et equalspour Floatet les Doubletypes: Ils traitent NaNdifféremment:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
Edit: Comme cela a été souligné dans un commentaire - "cela se produit également en Java" - dépend de ce que c'est exactement :
public static void main(final String... args) {
final double unboxedNaN = Double.NaN;
final Double boxedNaN = Double.valueOf(Double.NaN);
System.out.println(unboxedNaN == unboxedNaN);
System.out.println(boxedNaN == boxedNaN);
System.out.println(boxedNaN.equals(boxedNaN));
}
Cela imprimera
false
true
true
Donc, les unboxedNanrendements falsecomparé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 equalscas, ==à 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 Anyet se traduit par le double primitif et le double encadré si nécessaire. Ainsi, la scala ==se résume apparemment à une comparaison de NaNvaleurs primitives mais equalsutilise 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 doubles RichDouble).
Si vous avez vraiment besoin de savoir si quelque chose est réellement NaNutilisé isNaN: