user881423
user881423

Reputation: 125

Method in companion object compiled into static methods in scala?

It looks like scala compiles methods in companion objects into static methods, which makes invoking them from java code a little easier. For example, you could write CompanionObject.method() instead of CompanionObject$.MODULE$.method(). However, sometimes seemingly irrelevant code change will break this behavior. I came up with this example to illustrate the problem

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

So the only difference between TestCompanion and TestCompanion2 is that the latter is annotated with @SerialVersionUID, and init2 is compiled into a static method in TestCompanion but not in TestCompanion2.

Can someone explain why scalac treats these two classes differently? I don't see how the @SerialVersionUID annotation should affect the availability of static methods.

Upvotes: 6

Views: 1327

Answers (1)

Matthew Farwell
Matthew Farwell

Reputation: 61695

This is a known bug: Static forwarders are missing after adding @SerialVersionUID, raised by Josh Cough. From the description of the bug:

In the following code, adding @SerialVersionUID to the class results in the static forwarders missing from the byte code.

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

object WithUID {
 val instance = new WithUID
}
@SerialVersionUID(0) 
class WithUID extends scala.Serializable

Here is the relevant decompiled byte code:

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

Upvotes: 4

Related Questions