Scala Case Class disassembled

If we create a very simple Case Class in Scala:

$ echo 'case class TestCaseClass(a:Int)' > TestCaseClass.scala

and after compiling it we attempt to disassemble with:

javap -private TestCaseClass

we get:

public class TestCaseClass extends java.lang.Object implements scala.ScalaObject,scala.Product,scala.Serializable{
    private final int a;
    public static final scala.Function1 andThen(scala.Function1);
    public static final scala.Function1 compose(scala.Function1);
    public scala.collection.Iterator productIterator();
    public scala.collection.Iterator productElements();
    public int a();
    public TestCaseClass copy(int);
    public int copy$default$1();
    public int hashCode();
    public java.lang.String toString();
    public boolean equals(java.lang.Object);
    public java.lang.String productPrefix();
    public int productArity();
    public java.lang.Object productElement(int);
    public boolean canEqual(java.lang.Object);
    private final boolean gd1$1(int);
    public TestCaseClass(int);

Notice the wealth of helper classes created for us from the Scala compiler like the hashCode(), toString() and equals(..) methods that we routinely create in every new Java class we construct. Also our state variable is encapsulated as a constant and surprisingly we even get a factory method therefore reducing the need for calling new per each creation of instance objects.

Scala Class and Object disassembled

A Scala Class translates into an equivalent Java Class implementing scala.ScalaObject:

In Scala:

class TestScalaClass

if disassembled produces the following equivalent Java code:

public class TestScalaClass extends java.lang.Object implements scala.ScalaObject{
    public TestScalaClass();

The Scala Object which is Scala’s in-language support for Singleton Pattern:

object TestScalaObject

compiles into two bytecode files: TestScalaObject.class and TestScalaObject$.class.

TestScalaObject.class disassembles into:

public final class TestScalaObject extends java.lang.Object{

whereas TestScalaObject$.class disassembles into:

public final class TestScalaObject$ extends java.lang.Object implements scala.ScalaObject{
    public static final TestScalaObject$ MODULE$;
    public static {};

MODULE$ makes Scala to be accessible through Java.