Java 父類子類的對象初始化過程

1. 基本初始化過程:html

對於一個簡單類的初始化過程是:java

    static 修飾的模塊(static變量和static 塊)  ---> 按照代碼順序依次執行。函數

        |
this

    實例變量  及非static模塊---> 按照代碼順序依次執行。spa

        |
.net

    構造函數 ---> 執行對應的構造函數。code

子類的初始化過程。htm

    父類static修飾的模塊
對象

        |
blog

    子類static修飾模塊

        |

    父類實例變量和非static塊

        |

    父類對應構造函數。當子類對應構造函數中沒有顯示調用時調用的是父類默認的構造函數。

        |

    子類實例變量和非static塊

        |

    子類構造函數


Class的static模塊是惟一的,因此只初始化一次。全部類的實例公用Class的static模塊。

static模塊的初始化條件: ( From: 引用1 )

    (1)遇到new、getstatic、putstatic 或 invokestatic這4條字節碼指令時,若是類還沒初始化,則觸發初始化。對應場景是:new實例化對象時、讀或設置一個靜態字段時(被final修飾,已在編譯器把結果放入常量池的靜態字段除外),以及調用一個類的靜態方法時

    (2)對類進行反射調用時

    (3)初始化子類。但父類尚未初始化時,先觸發父類初始化

    (4)當虛擬機啓動時,需指定一個須要執行的主類(包含main方法),虛擬機會先初始化該類



2. 關於覆蓋和隱藏

    覆蓋:被覆蓋的方法至關於被擦除了,不可恢復(即便類型強制轉換也沒法調用)。

    隱藏:一直保存的某個位置,等須要的時候能夠繼續使用(類型強制轉換後能夠調用)。

關於父類子類之間的覆蓋和隱藏關係: (From :引用2)

    1. 父類的實例變量和類變量能被子類的同名變量隱藏。 

    2. 父類的靜態方法被子類的同名靜態方法隱藏,父類的實例方法被子類的同名實例方法覆蓋。 

    3. 不能用子類的靜態方法隱藏父類的實例方法,也不能用子類的實例方法覆蓋父類的靜態方法,不然編譯器會異常。 

    4. 用final關鍵字修飾的最終方法不能被覆蓋。 

    5. 變量只能被隱藏不會被覆蓋,子類的實例變量能夠隱藏父類的類變量,子類的類變量也能夠隱藏父類的實例變量。 


涉及的典型狀況:

前提:

-----------------------------------------

class B extends A{……}

-----------------------------------------

(1) B instanceB = new B();

instanceB的初始化過程如第一部分中:子類的初始化過程。

此時instanceB中實際上有一個super的所有信息(除了父類中被覆蓋的實例方法),可是當前的引用是子類的信息(若是子類中沒有的變量和方法則是從父類繼承來)。


(2)A instanceA = new B();

此時父類A的變量和靜態方法會將子類的變量和靜態方法隱藏。instanceA此時惟一可能調用的子類B的地方就是子類B中覆蓋了父類A中的實例方法。

執行 B instanceB = (B) instanceA; 後

此時instanceB至關於 B instanceB = new B();


注意:

    (1) 這裏惟一的覆蓋的狀況:父類的實例方法被子類的同名實例方法覆蓋。

    這裏方法調用變量時,其實是帶有一個默認的this的。也就是此實例方法中調用的是當前Class的值。涉及到繼承的狀況時,要十分注意super,this的狀況。

    (2) 在初始化的時候,有兩個階段。第一步是申請空間,第二步是賦值。

    具體見:

        static的值和final static值在初始化時的區別。(引用1)

        子類覆蓋父類實例方法時,調用子類的實例方法,而此時子類的實例方法調用了子類中的變量(此時static變量已經初始化,可是實例變量並無初始化)。(引用2)


這段代碼來自引用2,如何精煉,如此有趣。值得一看。

class Parent{
         int x=10;
         public Parent(){
              add(2);
         }
         void add(int y){
              x+=y;
         }
    }
     class Child extends Parent{
         int x=9;
         void add(int y){
              x+=y;
         }
         public static void main(String[] args){
              Parent p=new Child();
              System.out.println(p.x);
         } 
    }



引用 1. 類加載機制:

http://blog.csdn.net/kai_wei_zhang/article/details/8234146 

引用 2. 隱藏和覆蓋,以及一個好例子:

http://www.cnblogs.com/binjoo/articles/1585342.html

引用 3. 隱藏和覆蓋

http://renyanwei.iteye.com/blog/258304 

引用 4. 基本的初始化過程

http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html 

相關文章
相關標籤/搜索