比较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
。
有人可以解释这种意外行为吗?
答案 0 :(得分:3)
CharSequence
实际上是一个像String
和StringBuilder
这样的类实现的接口。 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已经声明了以下关于平等的内容(强调我的意思):
此接口不会优化
equals
和hashCode
方法的常规协定。 测试两个实现CharSequence的对象是否相等的结果通常是不确定的。每个对象都可以由不同的类实现,并且不能保证每个类都能够测试其实例与另一个实例的相等性。因此,将任意CharSequence实例用作集合中的元素或用作映射中的键是不合适的。
总结一下:忘记了您从String
和StringBuilder
中获得了subSequence
或reversed
。方法合约指定CharSequence
,因此您必须将其视为CharSequence
。无法保证这些函数将来仍会返回String
或StringBuilder
。
答案 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