根据变量类型的不同,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.equals(y)之前确实会执行y == 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)。有人能证实这是真的吗?
发布于 2019-09-20 17:56:21
这就是a contract for equals。x.equals(x)必须是真的。如果你破坏了合同,许多依赖它的东西将不再起作用。
编译器(例如集合库)必须假定对象是“行为良好的”。如果某些东西没有发生故障,那么它就不是编译器错误。
这样做的结果是,编译器可以在感觉上优化一些东西。在目前的情况下,当知道静态类型不需要BoxesRunTime.equals开销时,可以跳过该开销。
https://stackoverflow.com/questions/58025695
复制相似问题