Scala匹配和引用相等性检查

Scala匹配和引用相等性检查,scala,Scala,根据变量类型,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-ma

根据变量类型,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
检查。当变量的类型为
notequaltowny
时,我们得到一个标准的
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
)。有人能证实事实确实如此吗

x.equals(x)
必须为真。如果你违反了合同,很多依赖于它的东西将不再起作用

编译器(例如集合库)必须假定对象“行为良好”。如果某个东西没有损坏,那么它就不是一个编译器错误

这样做的结果是,编译器可以在自己喜欢的时候优化某些东西。在本例中,当已知静态类型不需要时,可以跳过
BoxesRunTime.equals
开销