Отличный результат использования equals() и == для GStringImpl

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

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

Вывод, который я получаю

true
false

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

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

3 ответа

Решение

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

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

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

Резюме

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

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

Но почему?

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

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

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

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

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

Так как Strings и GStrings реализуют Comparable E сть compareTo метод доступен.

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

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

Поведение == задокументировано здесь.

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

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

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

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

Оставив это здесь в качестве дополнительного ответа, чтобы его можно было легко найти для новичков в Groovy. Я явно преобразовываю GString в обычную строку перед ее сравнением.

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

приводит к

      false
true
Другие вопросы по тегам