All of the examples that compile (A
, B
, D
, E
) take exactly the same amount of storage space. In fact, even
class F(val bar: String) extends A(bar)
will have the data stored in one field--it just gets an extra accessor method for the same field. However, if you
class G(var bar: String) extends A(bar)
then a new field is constructed.
You can check all this by compiling your examples above and looking at the bytecode from javap -c Classname
(note the putfield at 2:
in the constructor of A
):
public class Sizes$A extends java.lang.Object implements scala.ScalaObject{
public java.lang.String foo();
Code:
0: aload_0
1: getfield #11; //Field foo:Ljava/lang/String;
4: areturn
public Sizes$A(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #11; //Field foo:Ljava/lang/String;
5: aload_0
6: invokespecial #18; //Method java/lang/Object."<init>":()V
9: return
}
(And the lack of an extra putfield in F
...)
public Sizes$F(java.lang.String);
Code:
0: aload_0
1: aload_1
2: invokespecial #15; //Method Sizes$A."<init>":(Ljava/lang/String;)V
5: return
(And the presence of one again in G
...)
public Sizes$G(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #11; //Field bar:Ljava/lang/String;
5: aload_0
6: aload_1
7: invokespecial #18; //Method Sizes$A."<init>":(Ljava/lang/String;)V
10: return