Подтвердить что ты не робот

Groovy разные результаты при использовании equals() и == на GStringImpl

Согласно groovy docs, == это просто "умный" equals(), так как он также заботится об исключении NullPointerException, Таким образом, == и equals() должны возвращать одно и то же значение, если объекты не равны нулю. Тем не менее, я получаю неожиданные результаты при выполнении следующих script:

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

Результат, который я получаю,

true
false

Пример этого можно найти здесь.

Это известная ошибка, связанная с GStringImpl или что-то, что мне не хватает?

4b9b3361

Ответ 1

Хороший вопрос, удивительная вещь о коде выше, что

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

возвращает false. Другая строка кода возвращает ожидаемый результат, поэтому забудьте об этом.

Резюме

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

Объект, вызываемый equals, имеет тип GStringImpl, тогда как 'test' имеет тип String, поэтому они не считаются равными.

Но почему?

Очевидно, что реализация GStringImpl equals могла быть написана так, что когда она передается String, которая содержит те же символы, что и this, она возвращает true. Prima facie, это кажется разумным делом.

Я предполагаю, что причина, по которой он не был написан таким образом, заключается в том, что он нарушит контракт equals, который гласит, что:

Он симметричен: для любых непустых опорных значений x и y x.equals(y) должен возвращать true тогда и только тогда, когда y.equals(x) возвращает true.

Реализация String.equals(Object other) всегда будет возвращать значение false при передаче GSStringImpl, поэтому, если GStringImpl.equals(Object other) возвращает значение true при передаче любого String, это будет нарушать симметричное требование.

Ответ 2

В groovy a == b сначала проверяется метод compareTo и использует a.compareTo(b) == 0, если существует метод compareTo. В противном случае он будет использовать equals.

Так как Strings и GStrings реализуют Comparable, существует доступный compareTo метод.

Следующее напечатает true, как ожидалось:

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

Поведение == описано здесь.

В Java == означает равенство примитивных типов или идентификаторов для объектов. В groovy == переводится на a.compareTo(b)==0, если они Comparable и a.equals(b) в противном случае. Для проверки подлинности существует is. Например. a.is(b).

Для других операторов см. эту таблицу: http://docs.groovy-lang.org/docs/latest/html/documentation/#Operator-Overloading

Связанная таблица предоставляется встроенной для потомков, в случае, если вышеупомянутая ссылка снова разрывается.

| 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()       |