【问题标题】:What code is generated for an equals/hashCode method of a case class?为 case 类的 equals/hashCode 方法生成什么代码?
【发布时间】:2011-05-30 10:16:48
【问题描述】:

我有一些 Java 代码要翻译成 Scala。

代码由一些不可变的类组成,这些类符合 Scala 中 case class 的目的。

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

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

第三,编译器添加方法的“自然”实现 toString, hashCode,并且等于你的类。

【问题讨论】:

    标签: java class scala equals hashcode


    【解决方案1】:

    Scala 有一个编译器选项-Xprint:typer,您可以使用它来获取“它在内部使用的打字后源代码”。

    scala -Xprint:typer -e 'case class Foo(a: String, b: Int)'
    

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

    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
    });
    

    但是,这并没有告诉您 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
    }
    

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

    case that: Foo => this.a == that.a && this.b == that.b
    

    【讨论】:

    • 这显示了 Product trait 的有用性。编译器不必为每个案例类生成自定义 hashCode(或 toString)。相反,它可以以非常通用的方式迭代对象的“元素”。也就是说,它结合了将状态存储在对象中和将其存储在 Map 中的优点。即对集合的通用操作。 Clojure 的 defrecord 表单提供了类似的好处。
    • 有趣。这意味着如果一个案例类有原始成员,那么无论何时调用 hashCode 都必须将它们装箱。
    • 从 scala 2.9 开始,为案例类生成的 hashCode 使用 MurmurHash。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 2018-03-03
    • 1970-01-01
    相关资源
    最近更新 更多