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.
In Scala there are no static methods: all methods are defined over an object, be it an instance of a class or a singleton, as the one you defined in your question.
A companion object is an object that's declared in the same file as a class , and has the same name as the class. A companion object and its class can access each other's private members. A companion object's apply method lets you create new instances of a class without using the new keyword.
Scala does not have static keyword, but still we can define them by using object keyword. The main design decision about this is that the clear separation between instance and static members.
Advantages of Companion Objects in Scala Companion objects provide a clear separation between static and non-static methods in a class because everything that is located inside a companion object is not a part of the class's runtime objects but is available from a static context and vice versa.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With