比较CharSequence.reversed()返回值时出现意外结果

时间:2019-01-17 12:37:49

标签: kotlin

比较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 :(得分:3)

CharSequence实际上是一个像StringStringBuilder这样的类实现的接口。 subSequence(0, 1)的结果不等于subSequence.reversed()的原因是由于它们返回的实际类型。

subSequence(0, 1)调用返回一个String,而reversed()返回一个StringBuilder。由于类型不同,因此equals-method将返回false

如果您根据toString()的结果调用reversed(),它将如您期望的那样工作:

val reversed = subSequence.reversed().toString()
println("$subSequence == $reversed: ${subSequence == reversed}") // Prints a == a: true 

答案 1 :(得分:0)

请注意,您可能对toString所显示的内容和equality (equals)的行为感到困惑。

您看到的是toString()的输出。任何类型都可以通过重写该方法来决定其对象的字符串表示形式。但是,这不会影响该类型的对象之间的比较。这就是equals(在某些情况下也是compare)的出现。

其他人写了一些关于比较对象的基础类型不相等的信息(一侧StringBuilder和另一侧String)。但是实际的问题是equals方法的问题。可能是(通常出于各种原因而不这样做),某个类型的equals支持不同类型的对象的相等性(至少应该在接口中提及这种行为)。如果未指定任何内容,则可以假定Object.equals中的默认等式成立。

然而,在这种情况下,CharSequence-javadoc已经声明了以下关于平等的内容(强调我的意思):

  

此接口不会优化equalshashCode方法的常规协定。 测试两个实现CharSequence的对象是否相等的结果通常是不确定的。每个对象都可以由不同的类实现,并且不能保证每个类都能够测试其实例与另一个实例的相等性。因此,将任意CharSequence实例用作集合中的元素或用作映射中的键是不合适的。

总结一下:忘记了您从StringStringBuilder中获得了subSequencereversed。方法合约指定CharSequence,因此您必须将其视为CharSequence。无法保证这些函数将来仍会返回StringStringBuilder

答案 2 :(得分:0)

转换回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
相关问题