Неожиданный результат при сравнении возвращаемого значения CharSequence.reversed () - PullRequest
0 голосов
/ 17 января 2019

Заметили странное поведение при сравнении результата метода CharSequence.reversed ().

val s = "a"
val subSequence = s.subSequence(0, 1)
println("$subSequence == ${subSequence.reversed()}: ${subSequence == subSequence.reversed()}")

Результат:

a == a: false

Более того subSequence.reversed() == subSequence.reversed() также false.

Может кто-нибудь объяснить это неожиданное поведение?

Ответы [ 3 ]

0 голосов
/ 17 января 2019

CharSequence на самом деле интерфейс, который реализуют классы, такие как String и StringBuilder. Причина, по которой результат subSequence(0, 1) не равен subSequence.reversed(), заключается в том, что они возвращают фактические типы.

Вызов subSequence(0, 1) возвращает String, а reversed() возвращает StringBuilder. Поэтому метод equals вернет false, потому что типы разные.

Это будет работать так, как вы ожидаете, если вы позвоните toString() по результату reversed():

val reversed = subSequence.reversed().toString()
println("$subSequence == $reversed: ${subSequence == reversed}") // Prints a == a: true 
0 голосов
/ 17 января 2019

Преобразование обратно в String устраняет проблему, потому что тогда применяется правильное (ожидаемое) eqauals:

val s = "a"
val subSequence = s.subSequence(0, 1)
println(subSequence.reversed() == subSequence.reversed()) //false
println(subSequence.reversed().toString() == subSequence.reversed().toString()) //true
0 голосов
/ 17 января 2019

Обратите внимание, что вас, вероятно, смущает то, что показано toString и как равенство (equals) .

То, что вы видите, является выводом toString(). Любой тип может решить, как может выглядеть его строковое представление, переопределив этот метод. Это, однако, не влияет на то, как объекты этого типа сравниваются друг с другом. Вот где приходит equals (в некоторых случаях также compare).

Другие писали что-то о том, что базовый тип сравниваемых объектов не равен (одна сторона StringBuilder, а другая String). Однако актуальная проблема заключается в методе equals. Возможно (обычно это не делается по разным причинам), что equals для определенного типа поддерживает равенство различных типов объектов (такое поведение (должно быть) должно быть упомянуто в интерфейсе по крайней мере). Если ничего не указано, можно предположить, что выполняется равенство по умолчанию из Object.equals.

В этом случае, однако, CharSequence -javadoc уже утверждает следующее о равенстве (выделено мной):

Этот интерфейс не уточняет общие контракты методов equals и hashCode. Поэтому результат проверки двух объектов, реализующих CharSequence на равенство, как правило, не определен . Каждый объект может быть реализован отдельным классом, и нет никакой гарантии, что каждый класс сможет проверить свои экземпляры на равенство с другими. Поэтому неуместно использовать произвольные экземпляры CharSequence в качестве элементов в наборе или в качестве ключей на карте.

Итак, подведем итоги: забудьте, что вы получили String или StringBuilder от subSequence и reversed. В контракте метода указывается CharSequence, поэтому вы должны обращаться с ним как CharSequence. Нет гарантии, что эти функции все равно будут возвращать String или StringBuilder в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...