scala - 在不使构造函数参数成为对象成员的情况下创建对象

Sac*_*kar 3 scala class object

我有

class Address(elem: scala.xml.Elem){
    val attr1 = (elem \ "attr1") text
    ...
}
Run Code Online (Sandbox Code Playgroud)

我不希望elem成为Address的成员,因为我在内存中创建了数百万个这样的对象,因此将占用空间保持在最小.什么是scala方法来实现这一目标?谢谢.

Rex*_*err 11

你只是以你展示的方式实现它.只要确保你只是elem作为类初始化程序的一部分引用,而不是在必须存储它的其他方法中,以便可以调用它.

这是您编写的字节码(javap -p ClassName在编译的类上使用):

public Address(scala.xml.Elem);
  Code:
   0:   aload_0
   1:   invokespecial   #18; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aload_1
   6:   ldc #19; //String attr1
   8:   invokevirtual   #25; //Method scala/xml/Elem.$bslash:(Ljava/lang/String;)Lscala/xml/NodeSeq;
   11:  invokevirtual   #30; //Method scala/xml/NodeSeq.text:()Ljava/lang/String;
   14:  putfield    #11; //Field attr1:Ljava/lang/String;
   17:  return
Run Code Online (Sandbox Code Playgroud)

请注意,只有一个putfield,即初始化val的那个attr1.如果elem被保存在类中,它将需要它自己的putfield.如果你val改为a def,你会得到:

public Address(scala.xml.Elem);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield    #12; //Field elem:Lscala/xml/Elem;
   5:   aload_0
   6:   invokespecial   #31; //Method java/lang/Object."<init>":()V
   9:   return
Run Code Online (Sandbox Code Playgroud)

在那里你可以看到Elem已经存储了所以def可以在每次调用时使用它.

如果你Elem存储和访问,你就必须声明类

class Address(val elem: scala.xml.Elem) { ... }
Run Code Online (Sandbox Code Playgroud)

(注意val).

只有在使用case类时才会始终存储构造函数参数:case类是为模式匹配而设计的,当然,如果您稍后尝试匹配它,则需要存储参数.