为什么Scala案例类会生成两个apply方法?

时间:2018-07-18 17:27:32

标签: scala

我正在尝试探索scala case类的内部结构。为此,我正在创建简单的案例类并分析scala编译器使用javap创建的字节码。

我很惊讶地发现,当我创建一个只有一个String字段的case类时:

case class MyCaseClass(value: String)

伴随对象MyCaseClass$的字节码包含两个apply方法:

  public MyCaseClass apply(java.lang.String);
    Code:
       0: new           #23                 // class MyCaseClass
       3: dup
       4: aload_1
       5: invokespecial #26                 // Method MyCaseClass."<init>":(Ljava/lang/String;)V
       8: areturn

  public java.lang.Object apply(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #53                 // class java/lang/String
       5: invokevirtual #55                 // Method apply:(Ljava/lang/String;)LMyCaseClass;
       8: areturn

(使用scalac 2.11.6编译)

第一个是我期望的-将String作为参数,并创建我的case类的新实例,并将此参数传递给构造函数。第二个对象获取一个对象,将其强制转换为String,然后调用第一个对象。

我想不出第二种方法的任何用途。为什么需要它?此行为记录在任何地方吗?

1 个答案:

答案 0 :(得分:3)

默认的伴随对象扩展了函数类型,在这种情况下为Function1[String, MyCaseClass](在Scala中通常写为String => MyCaseClass)。

Function1#apply的JVM签名为Object apply(Object),因此覆盖方法必须具有相同的签名。