为case类的equals/hashCode方法生成了什么代码?

soc*_*soc 24 java scala class equals hashcode

我有一些Java代码,我正在翻译成Scala.

代码由一些不可变的类组成,这些类符合case classScala中的目的.

但我不想引入错误,因此我想确保为当前实现生成的代码equalshashCode/ 和/的行为等效.

我已经看过"Scala编程",但它只是说

第三,编译器将方法的"自然"实现添加到String,hashCode,并且等于你的类.

Bra*_*ord 45

Scala有一个编译器选项-Xprint:typer,您可以使用它来获取"内部使用的后置输入源代码".

scala -Xprint:typer -e 'case class Foo(a: String, b: Int)'
Run Code Online (Sandbox Code Playgroud)

在这里你看到类似的东西:

override def hashCode(): Int = ScalaRunTime.this._hashCode(Foo.this);
override def toString(): String = ScalaRunTime.this._toString(Foo.this);
override def equals(x$1: Any): Boolean = Foo.this.eq(x$1).||(x$1 match {
  case (a: String,b: Int)this.Foo((a$1 @ _), (b$1 @ _)) if a$1.==(a).&&(b$1.==(b)) => x$1.asInstanceOf[this.Foo].canEqual(Foo.this)
  case _ => false
});
Run Code Online (Sandbox Code Playgroud)

但是,这并没有告诉您如何生成hashCode.这是源头:

def _hashCode(x: Product): Int = {
  var code = x.productPrefix.hashCode()
  val arr =  x.productArity
  var i = 0
  while (i < arr) {
    val elem = x.productElement(i)
    code = code * 41 + (if (elem == null) 0 else elem.hashCode())
    i += 1
  }
  code
}
Run Code Online (Sandbox Code Playgroud)

而且,在这个例子中,equals模式匹配的第一种情况就是:

case that: Foo => this.a == that.a && this.b == that.b
Run Code Online (Sandbox Code Playgroud)

  • 这显示了产品特性的有用性.编译器不必为每个案例类生成自定义hashCode(或toString).相反,它可以以非常通用的方式迭代对象的"元素".也就是说,它结合了在对象中存储状态并将其存储在Map中的好处.即,对集合的通用操作.Clojure的defrecord形式提供了类似的好处. (14认同)
  • 有趣.这意味着如果一个case类有原始成员,那么每当调用hashCode时,它们都必须被装箱. (2认同)
  • 从scala 2.9开始,为案例类生成的hashCode使用MurmurHash。 (2认同)