伴随对象中的方法在scala中编译成静态方法?

use*_*423 6 scala

看起来scala将伴随对象中的方法编译为静态方法,这使得从java代码调用它们更容易一些.例如,您可以编写CompanionObject.method()而不是CompanionObject $ .MODULE $ .method().但是,有时看似无关的代码更改会破坏这种行为.我想出了这个例子来说明问题

$ cat TestCompanion.scala 
class TestCompanion

object TestCompanion {
  def init2 {}
}

@SerialVersionUID(1L)
class TestCompanion2

object TestCompanion2 {
  def init2 {}
}


$ scalac -version
Scala compiler version 2.9.0.1 -- Copyright 2002-2011, LAMP/EPFL

$ scalac TestCompanion.scala
$ javap TestCompanion
Compiled from "TestCompanion.scala"
public class TestCompanion extends java.lang.Object implements scala.ScalaObject{
    public static final void init2();
    public TestCompanion();
}

$ javap TestCompanion2
Compiled from "TestCompanion.scala"
public class TestCompanion2 extends java.lang.Object implements scala.ScalaObject{
    public static final long serialVersionUID;
    public static {};
    public TestCompanion2();
}
Run Code Online (Sandbox Code Playgroud)

所以TestCompanion和TestCompanion2之间的唯一区别是后者用@SerialVersionUID注释,init2在TestCompanion中编译成静态方法,但在TestCompanion2中没有.

有人可以解释为什么scalac以不同的方式对待这两个类吗?我没有看到@SerialVersionUID注释如何影响静态方法的可用性.

Mat*_*ell 4

这是一个已知的错误:添加 @SerialVersionUID 后静态转发器丢失,由 Josh Cough 提出。从bug的描述来看:

在以下代码中,将 @SerialVersionUID 添加到类会导致字节代码中缺少静态转发器。

object WithoutUID {
 val instance = new WithoutUID
}
class WithoutUID extends scala.Serializable

object WithUID {
 val instance = new WithUID
}
@SerialVersionUID(0) 
class WithUID extends scala.Serializable
Run Code Online (Sandbox Code Playgroud)

以下是相关的反编译字节码:

public class WithoutUID implements Serializable, ScalaObject {
  public static final WithoutUID instance(){
    return WithoutUID.MODULE$.instance();
  }
}

public class WithUID implements Serializable, ScalaObject {
  public static final long serialVersionUID = 0L;
}
Run Code Online (Sandbox Code Playgroud)