取决于变量类型,Scala有时匹配值,有时不匹配。 这个简单的程序说明了这个问题:
class NotEqualToAnything {
override def equals(obj: Any): Boolean = false
}
val x = new NotEqualToAnything()
x match {
case `x` =>
println("WTF x equal to itself")
case _ =>
println("no-match") // This got printed
}
val y: AnyRef = new NotEqualToAnything()
y match {
case `y` =>
println("WTF y equal to itself") // This got printed
case _ =>
println("no-match")
当变量的类型为AnyRef
时,生成的代码包含对BoxesRunTime.equals
的调用,该调用实际上在调用y == y
之前进行了y.equals(y)
检查。当变量的类型为NotEqualToAnything
时,我们进行了两次标准的x == null
检查,然后调用了x.equals(x)
。
我对此进行了测试
Scala 2.13.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_201).
我想知道这是否是编译器错误,是否应该报告这是否是“期望的”行为。我认为这两种情况的行为应相同。
一种假设是,编译器期望类在重写equals
时遵循协定,因此期望equals
具有反射性(x.equals(x) == true
)。有人可以确认确实如此吗?
答案 0 :(得分:5)
有a contract for equals
。 x.equals(x)
必须为真。如果您违反该合同,那么依赖它的很多事情将不再起作用。
编译器(例如收集库)必须假定对象是“行为良好的”。如果某些东西没有破坏,那不是编译器错误。
其结果是编译器可以在感觉上优化某些东西。在当前情况下,当已知静态类型不需要BoxesRunTime.equals
开销时即可。