2011-12-02 131 views
4

我是新來的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; 
} 

讓我們只考慮javap傾倒的ColorPoint構造函數的字節碼。如果代碼包括關鍵語句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之前被初始化,即基地初始化之前。

那麼是什麼原因?任何文件/文章都指定了這種行爲?

順便說一句,我的scala版本是2.7.7final(OpenJDK Server VM,Java 1.6.0_20)。感謝和最好的問候!

+0

在這樣一個過時的版本上運行的任何理由?你需要幫助遷移嗎? – soc

+0

@soc已經升級了,謝謝。 –

回答