Отличный результат использования 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