1. 程式人生 > >Java子父類中的建構函式例項化過程

Java子父類中的建構函式例項化過程

其實我們發現子類繼承父類操作很簡單,如果要是去深入的研究下會發現,例項化過程並非是我們看到的那樣,我們就以程式碼舉例來說明;

問大家,以下程式碼執行會輸出什麼呢?

package com.oop;

/**
 * 定義動物物件
 * @author Liudeli
 *
 */
class Animal {

    public Animal() {
        System.out.println("Animal()--建構函式");
    }

}

/**
 * 定義狗物件
 * @author Liudeli
 *
 */
class Dog extends Animal{
} /** * 子父類中的建構函式例項化過程 * @author Liudeli * */ public class Demo1 { public static void main(String[] args) { Dog d = new Dog(); } }

沒有去深究這個問題,大部分會回答,不輸出任何,因為Dog類沒有任何構造方法,如果這樣想的其實就錯了,它一定會輸出父類無參構造方法的內容:

這裡寫圖片描述

這是為什麼呢?
答:其實只要我們隨便建立一個類,就會有隱式的程式碼重點內容執行
會在子類的構造方法中執行 super(); 呼叫

/**
 * 定義狗物件
 * @author Liudeli
 *
 */
class Dog extends Animal{

    // 其實只要我們隨便建立一個類,就會有隱式的程式碼執行,只是我們看不到而已
    Dog() {
        super();
        return;
    }

}

子類有一個有參構造方法,new 子類(true),呼叫子類的有參構造方法,父類的無參構造方法一定會執行,因為在子類的任何構造方法中,都會預設呼叫 super();

package com.oop;

/**
 * 定義動物物件
 * @author Liudeli
 *
 */
class Animal2 { public Animal2() { System.out.println("Animal()--建構函式"); } public Animal2(boolean is) { System.out.println("Animal2(boolean is)--建構函式 is:" + is); } } /** * 定義狗物件 * @author Liudeli * */ class Dog2 extends Animal{ public Dog2() { } public Dog2(boolean is) { System.out.println("Dog2(boolean is)--建構函式 is:" + is); } } /** * 子父類中的建構函式例項化過程 * @author Liudeli * */ public class Demo2 { public static void main(String[] args) { // 我呼叫的是,子類的有參構造方法,父類的無參構造方法會執行 // 因為在子類的任何構造方法中,都會執行super(); Dog2 dog = new Dog2(true); } }

執行結果:
這裡寫圖片描述

我們看不到的細節:

package com.oop;

/**
 * 定義動物物件
 * @author Liudeli
 *
 */
class Animal3 {

    public Animal3() {
        System.out.println("Animal()--建構函式");
    }

    public Animal3(boolean is) {
        System.out.println("Animal(boolean is)--建構函式 is:" + is);
    }

}

/**
 * 定義狗物件
 * @author Liudeli
 *
 */
class Dog3 extends Animal{


    public Dog3() {
        // super(); 預設就有,只是我們看不到而已,super()它在子類任何建構函式中的第一行
        super(false);  // 這樣寫報錯,為什麼會報錯因為在子類的任何建構函式中都會執行 super()
                       // 你如果寫了 super(引數); 就是不認它呼叫父類的super(), 所以它會報錯
    }

    public Dog3(boolean is) {
        // super(); 預設就有,只是我們看不到而已,super()它在子類任何建構函式中的第一行
        super(false);  // 這樣寫報錯,為什麼會報錯因為在子類的任何建構函式中都會執行 super()
                       // 你如果寫了 super(引數); 就是不認它呼叫父類的super(), 所以它會報錯
        System.out.println("Dog(boolean is)--建構函式 is:" + is);
    }

}

/**
 * 子父類中的建構函式例項化過程
 * @author Liudeli
 *
 */
public class Demo3 {

    /*
     *  Demo3 的例項化必須執行以下程式碼,只是隱式的看不到而已
     */
    // 主要 修飾符 public 是由於類開始定義的是public,所以它才是public,修飾符根據類的定義變化而變化
    public Demo3() {
        super();
        return;
    }

    public static void main(String[] args) {

        Dog3 dog = new Dog3(true);

    }

}

在這裡有一個思考點,建立一個類不繼承任何類,預設無參建構函式必須執行 super(); ,那super呼叫了那個父類的無參建構函式?

答:最終超類 Object。

所以我們這樣寫,沒有任何問題,extends Object

package com.oop;

// 系統預設或直接間接的讓Object成為了父類,extends Object,只是我們看不到而已
public class Demo4 extends Object {  

    /*
     *  Demo3 的例項化必須執行以下程式碼,只是隱式的看不到而已
     */
    // 主要 修飾符 public 是由於類開始定義的是public,所以它才是public,修飾符根據類的定義變化而變化
    public Demo4() {
        super();
        return;
    }

    public static void main(String[] args) {
        System.out.println("Demo4()...");
    }

}

執行結果:
這裡寫圖片描述

父類寫了一個有參構造方法,子類繼承父類,子類必須要寫一個和父類一樣引數的構造方法,因為父類寫了一個有參構造方法,父類的無參構造方法就沒有了,子類的無參構造方法就呼叫不到父類的無參構造方法了,需要讓子類的有參構造方法去super()呼叫;

public  class Observer {

    private String name;
    private Secretary secretary;

    public Observer(String name, Secretary secretary) {
        this.name = name;
        this.secretary = secretary;
    }

}
public class StockObserver extends Observer{

    // 子類必須要寫一個和父類同參的構造方法
    public StockObserver(String name, Secretary secretary) {
        super(name, secretary);
        // TODO Auto-generated constructor stub
    }
}