Inheritance 使用构造函数参数扩展scala中的类是否会向该类添加VAL(字段)?
假设我有:Inheritance 使用构造函数参数扩展scala中的类是否会向该类添加VAL(字段)?,inheritance,scala,Inheritance,Scala,假设我有: class A(val foo: String) class B(foo: String) extends A(foo) class C(val foo: String) extends A(foo) class D(override val foo: String) extends A(foo) class E(bar: String) extends A(bar) 我感兴趣的是每个类的实例占用多少内存。类的实例将有一个成员变量:foo B、C、D和E班怎么样?它们每个都有多少
class A(val foo: String)
class B(foo: String) extends A(foo)
class C(val foo: String) extends A(foo)
class D(override val foo: String) extends A(foo)
class E(bar: String) extends A(bar)
我感兴趣的是每个类的实例占用多少内存。类的实例将有一个成员变量:foo
B、C、D和E班怎么样?它们每个都有多少个成员变量?我怀疑E会有两个(E.bar,A.foo),我希望D会有一个(A.foo),但我想知道B和C,他们会有两个吗?(B.foo,A.foo)?您的类
C
需要在val foo
上使用override
关键字进行编译,使其与D
相同。它将存储自己的foo副本。类B
不会添加存储,除非在其构造函数主体之外的某个地方有对foo
的引用。这将强制创建一个隐藏字段来保存构造函数参数。构造函数主体是类定义内和任何方法主体外的所有代码
增编:
package storage
class A(val foo: String)
class B( foo: String) extends A(foo)
// class C( val foo: String) extends A(foo)
class D(override val foo: String) extends A(foo)
class E( bar: String) extends A(bar)
class F( bar: String) extends A(bar) { def barbar: String = bar }
我对此感到困惑:
% javap -private storage.F
Compiled from "Storage.scala"
public class storage.F extends storage.A implements scala.ScalaObject{
public java.lang.String barbar();
public storage.F(java.lang.String);
}
barbar使用什么方法来获取其返回值?所有编译的示例(
A
,B
,D
,E
)占用的存储空间量完全相同。事实上,甚至
class F(val bar: String) extends A(bar)
将数据存储在一个字段中——它只为同一字段获取一个额外的访问器方法。然而,如果你
class G(var bar: String) extends A(bar)
然后构造一个新字段
您可以通过编译上面的示例并查看javap-c Classname
中的字节码(注意A
的构造函数中2:
处的putfield)来检查所有这一切:
(并且在G
中再次出现一个)
public size$G(java.lang.String);
代码:
0:aload_0
1:aload_1
2:putfield#11//字段栏:Ljava/lang/String;
5:aload_0
6:aload_1
7:特别是#18//方法大小为$A.“”:(Ljava/lang/String;)V
10:返回
请注意,var和val都在Scala生成的类文件上创建方法。字段的生成对于用户来说有点不透明,因此您不能依赖生成的任何特定字段或此类字段的名称。B
也不会为foo
添加字段,以防您在构造函数体之外访问它,而是使用父级的访问器。感谢您提供的信息。只是想澄清一下:你是说D的实例将有两个foo的副本吗?@alexblack:是的。javap
命令有助于披露这些细节,但请注意,您需要使用它的-private
选项查看支持编译器用于调解对这些字段的访问的访问器(和mutator)方法的所有私有字段。
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
}
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
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