web-dev-qa-db-fra.com

Groovy différents résultats sur l'utilisation de equals () et == sur un GStringImpl

Selon les groovy docs , le == est juste un égal à 'intelligent' () car il prend également soin d'éviter NullPointerException. Ainsi, == et equals () devraient retourner la même valeur si les objets ne sont pas nuls. Cependant, j'obtiens des résultats inattendus sur l'exécution du script suivant:

println "${'test'}" == 'test'
println "${'test'}".equals('test')

La sortie que je reçois est

true
false

Un exemple de ceci peut être trouvé ici .

Est-ce un bug connu lié à GStringImpl ou quelque chose qui me manque?

50
Anuj Arora

Belle question, la chose surprenante sur le code ci-dessus est que

println "${'test'}".equals('test')

renvoie false. L'autre ligne de code renvoie le résultat attendu, alors oublions cela.

Sommaire

"${'test'}".equals('test')

L'objet appelé equals est de type GStringImpl tandis que 'test' Est de type String, ils ne sont donc pas considérés comme égaux.

Mais pourquoi?

Évidemment, l'implémentation de GStringImpl de equals aurait pu être écrite de telle sorte que lorsqu'elle est passée un String contenant les mêmes caractères que this, elle renvoie vrai. À première vue, cela semble être une chose raisonnable à faire.

Je suppose que la raison pour laquelle il n'a pas été écrit de cette façon est qu'il violerait le contrat equals, qui stipule que:

Il est symétrique: pour toutes les valeurs de référence non nulles x et y, x.equals (y) doit retourner vrai si et seulement si y.equals (x) retourne vrai.

L'implémentation de String.equals(Object other) retournera toujours false lorsqu'elle est passée à GSStringImpl, donc si GStringImpl.equals(Object other) retourne vrai lorsqu'elle est passée à String, ce serait en violation de l'exigence symétrique.

62
Dónal

Dans groovy a == b Recherche d'abord une méthode compareTo et utilise a.compareTo(b) == 0 si une méthode compareTo existe. Sinon, il utilisera equals.

Étant donné que Strings et GStrings implémentent Comparable, une méthode compareTo est disponible.

Les impressions suivantes sont vraies, comme prévu:

println "${'test'}".compareTo('test') == 0

Le comportement de == Est documenté ici .

In Java == Signifie égalité des types primitifs ou identité des objets. Dans Groovy == Se traduit par a.compareTo(b)==0, s'ils sont Comparable et a.equals(b) sinon. Pour vérifier l'identité, il y a is. Par exemple a.is(b).

Pour les autres opérateurs, voir ce tableau: http://docs.groovy-lang.org/docs/latest/html/documentation/#Operator-Overloading

Tableau lié fourni en ligne pour la postérité, au cas où le lien ci-dessus se rompt à nouveau.

| Operator | Method                  |
|----------|-------------------------|
| +        | a.plus(b)               |
| a[b]     | a.getAt(b)              |
| -        | a.minus(b)              |
| a[b] = c | a.putAt(b, c)           |
| *        | a.multiply(b)           |
| a in b   | b.isCase(a)             |
| /        | a.div(b)                |
| <<       | a.leftShift(b)          |
| %        | a.mod(b)                |
| >>       | a.rightShift(b)         |
| **       | a.power(b)              |
| >>>      | a.rightShiftUnsigned(b) |
| |        | a.or(b)                 |
| ++       | a.next()                |
| &        | a.and(b)                |
| --       | a.previous()            |
| ^        | a.xor(b)                |
| +a       | a.positive()            |
| as       | a.asType(b)             |
| -a       | a.negative()            |
| a()      | a.call()                |
| ~a       | a.bitwiseNegate()       |
44
Dunes