初始化順序(Thinking in Java中的一段有意思的例子)

abstract class Glyph {
  abstract void draw();
  Glyph() {
    System.out.println("Glyph() before draw()");
    draw();
    System.out.println("Glyph() after draw()");
  }
}

class RoundGlyph extends Glyph {
  int radius = 1;
  RoundGlyph(int r) {
    radius = r;
    System.out.println(
      "RoundGlyph.RoundGlyph(), radius = "
      + radius);
  }
  void draw() {
    System.out.println(
      "Draw():RoundGlyph.draw(), radius = " + radius);
  }
}

public class PolyConstructors {
  public static void main(String[] args) {
    new RoundGlyph(5);
  }
}
這是Thinking in Java中多態一章中的一個例子,程序運行的結果是什麼呢,首先應該分析一下代碼。
在分析這段代碼之前,需要知道的是:
(1) 在採取其他任何操作之前,爲對象分配的存儲空間初始化成二進制零。
(2) 子類首先調用基礎類構建器。
(3) 按照原先聲明的順序調用成員初始化代碼。
(4) 調用衍生類構建器的主體。
由這四點可以知道,在主函數實例化一個RoundGlyph,調用它的構造函數,發現它是一個繼承了Ploy的類,那麼首先在構造器內隱式調用父類構造器,在這時,由第一條我們知道,這時候radius的值被初始化爲0了,然後執行父類構造器,得到了第一個輸出"Glyph() before draw()",執行下一行,要調用虛函數draw(),自動找到了子類的覆蓋的函數draw(),執行得到了第二行輸出"Draw():RoundGlyph.draw(), radius = 0",注意,這裏是0而不是子類的賦值1,因爲這裏還沒有執行到子類的賦值,所以只得到虛擬機爲該變量的初始化0,然後執行下一行得到了"Glyph() after draw()",然後爲子類初始化成員變量得到radius的值爲1,然後執行構造器得到了radius的值爲5,然後輸出"RoundGlyph.RoundGlyph(), radius = 5",所以最後得到的輸出結果應該是:
Glyph() before draw()
Draw():RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章