我是java中的scala新手,并被固有层次结构中scala的对象初始化序列所困惑。IIRC,在Java中,如果子类的对象被初始化,则在其自己的构造函数的任何代码之前调用其基类的构造函数。在scala中,我得到了完全不同的行为。考虑以下示例:

class Point(val x: Int, val y: Int){
    val name = this.makeName;

    def makeName: String = {
        println("makeName at super.");

        "[" + x + ", " + y + "]";
    }

    override def toString: String = name;
}

class ColorPoint(override val x: Int, override val y: Int, var color: String) extends Point(x, y) {

    // key statement
    println(name);

    override def makeName: String = {
        println("makeName at sub.");

        super.makeName + ":" + myColor;
    }

    val myColor = color;

    override def toString: String = name;
}

让我们只考虑构造函数的字节代码 ColorPoint 倾倒与 javap.如果代码包括关键语句 println(name); 字节码为

public ColorPoint(int, int, java.lang.String);
  Code:
   0:   aload_0
   1:   aload_3
   2:   putfield        #13; //Field color:Ljava/lang/String;
   5:   aload_0
   6:   iload_1
   7:   iload_2
   8:   invokespecial   #18; //Method Point."<init>":(II)V
   11:  getstatic       #24; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   14:  aload_0
   15:  invokevirtual   #28; //Method name:()Ljava/lang/String;
   18:  invokevirtual   #32; //Method scala/Predef$.println:(Ljava/lang/Object;)V
   21:  aload_0
   22:  aload_3
   23:  putfield        #34; //Field myColor:Ljava/lang/String;
   26:  return

我们可以看到菲尔德 myColor 初始化后 invokespecial, ,即基类初始化后。

如果我把声明注释掉 println(name); 字节码为:

public ColorPoint(int, int, java.lang.String);
  Code:
   0:   aload_0
   1:   aload_3
   2:   putfield        #13; //Field color:Ljava/lang/String;
   5:   aload_0
   6:   aload_3
   7:   putfield        #15; //Field myColor:Ljava/lang/String;
   10:  aload_0
   11:  iload_1
   12:  iload_2
   13:  invokespecial   #20; //Method Point."<init>":(II)V
   16:  return

我们看到那个领域 myColor 就在初始化之前 invokespecial, ,即base初始化之前。

那原因是什么?任何文档/文章指定这种行为?

顺便说一句,我的scala版本是2.7.7final(OpenJDK Server VM,Java1.6.0_20)。谢谢,并致以最良好的问候!

有帮助吗?

解决方案

编译器只是按顺序执行事物。这里有一些文档。

https://github.com/paulp/scala-faq/wiki/Initialization-Order

从它的主要部分如下。

  1. 超类在子类之前完全初始化。
  2. 否则,按声明顺序。
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top