天天看點

子類的初始化過程、記憶體結構

一、首先先看引例

public class Father {
     public Father() {  
        say();  
    }  

    public void say() {  
        System.out.println("I'm father");  
    }  
}
           
public class Son extends Father{
    private int i = 11;  

    public Son() {
    }

    @Override  
    public void say() {  
        System.out.println("I'm son " + i);  
    }  
}           
public class Test {
    public static void main(String[] args) {
        Son son = new Son();  
    }
}           

列印如下:

子類的初始化過程、記憶體結構

二、分析

  • 首先要明确一點,類和【加載】和【初始化,又稱執行個體化】不是一個概念,
    • 類加載後并不一定執行個體化,但是類初始化前需要先被加載。
      • 對于上面這個程式,請問【 Father會被初始化嗎?】
    • 下面開始分析:
    • ①類加載器加載Test類到方法區。
    • ②開始執行main方法,main方法入棧。
    • ③由程式計數器擷取第一條指令。
    • ④new Son();
    • –>需要初始化Son,但是由于Son繼承Father,是以類加載器先加載Father到方法區。
    • 并在new Son()的堆記憶體中分一部分用來儲存繼承自父類Father的成員變量資訊,暫稱為子類父空間。
    • –>然後加載Son到方法區。調用父類的構造方法,調用自己的構造方法。
      • 我們知道:
    • ①子類中定義的成員變量和父類中定義的成員變量相同時,則父類中的成員變量不能被繼承。
    • ②子類中定義的成員方法,并且這個方法的名字傳回類型,以及參數個數和類型與父類的某個成員方法完全相同,則父類的成員方法不能被繼承。

      總結:相同的方法會被重寫,變量沒有重寫之說,如果子類聲明了跟父類一樣的變量,那意味着子類将有兩個相同名稱的變量。一個存放在子類對象中,一個存放在子類父空間中。父類的private變量,也會被繼承并且初始化在子類父對象中,隻不過對外不可見。是以,子類和父類的方法都是放在子類對象的記憶體中,而不是子類父空間中。

子類的初始化過程、記憶體結構

其實對于Father類來說,不也可以說的被初始化了嗎?被Son對象初始化了?