多態/構造器的調用順序/構造器內部的多態

Java實現多態的機制是後期綁定。
但Java也有些地方可以用前期綁定,比如:final,static,private(隱式final)和構造方法(隱式static)是前期綁定。
另外,Java只有普通方法的調用可以是多態的,如果直接訪問某個域,這個訪問將在編譯期進行解析。
舉例

//子類
public class Son extends Battle {
    public int a = 2;
    public int getA(){
        return a;
    }
}
//父類
public class Battle {
	public int a = 1;
	public int getA(){
		return a;
	}
	public static void main(String[] args) throws Exception {
		Battle b = new Son();
		System.out.println(b.a);
		System.out.println(b.getA());
    }
}

輸出
在這裏插入圖片描述


構造器調用順序
先看如下代碼

class Meal {
    Meal() { System.out.println("Meal()"); }
}
class Bread {
    Bread() { System.out.println("Bread()"); }
}
class Cheese {
    Cheese() { System.out.println("Cheese()"); }
}
class Lettuce {
    Lettuce() { System.out.println("Lettuce()"); }
}
class Lunch extends Meal {
    Lunch() { System.out.println("Lunch()"); }
}
class PortableLunch extends Lunch {
    PortableLunch() { System.out.println("PortableLunch()"); }
}
public class Test extends PortableLunch {
    private Bread b = new Bread();
    private Cheese c = new Cheese();
    private Lettuce l = new Lettuce();
    public Test() { System.out.println("Test()"); }
    public static void main(String[] args) {
        new Test();
    }
}

輸出
在這裏插入圖片描述
執行步驟是:
1、調用父類構造器。這個步驟會不斷遞歸下去,直到構造這種層次結構的根,然後是下一層的子類,直到最底層的子類。
1、按聲明順序調用成員的初始化方法。
3、調用子類構造器的主體。
同時調用層次中某一類的構造方法時,會先初始化成員變量。
按如下順序初始化類中的東西:

1、靜態屬性初始化
2、靜態方法塊初始化
3、普通屬性初始化
4、普通方法塊初始化
5、構造函數初始化

構造器內部的多態
先看代碼

class Glyph{
    void draw(){
        System.out.println("Glyph draw()");
    }
    Glyph(){
        System.out.println("Glyph() before draw()");
        draw();
        System.out.println("Glyph() after fraw()");
    }
}
class RoundGlyph extends Glyph{
    private int radius = 1;
    RoundGlyph(int r){
        radius = r;
        System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
    }
    void draw(){
        System.out.println("RoundGlyph.draw(), radius = " + radius);
    }
}
public class Test {
    public static void main(String[] args) {
        new RoundGlyph(5);
    }
}

輸出
在這裏插入圖片描述
分析一下代碼運行過程:

  1. 在其他任何事物發生之前,將分配給對象的存儲空間初始化爲二進制的零。
  2. 如上文一般,虛擬機在查看類的類型信息的時候,如果發現有父類,則繼續去加載父類的類文件,如果沒有父類了,則開始初始化類,再然後執行構造器。
  3. 這時在執行Glyph的構造器時發現它調用了子類重寫的draw方法,在這是一個多態。由於子類還沒有初始化,這時radius是剛開始分配存儲空間時初始化的0,因此打印出 RoundGlyph.draw(), radius = 0。
  4. 按照聲明的順序調用成員的初始化方法。
  5. 調用子類的構造器。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章