Отличный результат использования equals () и == для GStringImpl - PullRequest
48 голосов
/ 13 марта 2012

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

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

Я получаю вывод

true
false

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

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

Ответы [ 2 ]

61 голосов
/ 13 марта 2012

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

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

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

Сводка

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

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

Но почему?

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

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

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

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

44 голосов
/ 13 марта 2012

В 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 / Документация / # Перегрузка оператора

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

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