Groovy разные результаты при использовании equals() и == на GStringImpl
Согласно groovy docs, == это просто "умный" equals(), так как он также заботится об исключении NullPointerException, Таким образом, == и equals() должны возвращать одно и то же значение, если объекты не равны нулю. Тем не менее, я получаю неожиданные результаты при выполнении следующих script:
println "${'test'}" == 'test'
println "${'test'}".equals('test')
Результат, который я получаю,
true
false
Пример этого можно найти здесь.
Это известная ошибка, связанная с GStringImpl или что-то, что мне не хватает?
Ответы
Ответ 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() |