1. 程式人生 > >Java繼承機制的初始化順序+靜態動態繫結

Java繼承機制的初始化順序+靜態動態繫結

 一個Java程式的執行要經過編譯和執行(解釋)這兩個步驟,同時Java又是面向物件的程式語言。當子類和父類存在同一個方法,子類重寫了父類的方法,程式在執行時呼叫方法是呼叫父類的方法還是子類的重寫方法呢,這應該是我們在初學Java時遇到的問題。這裡首先我們將確定這種呼叫何種方法實現或者變數的操作叫做繫結。(執行父類方法還是子類方法是由物件決定的,跟引用沒有直接關係

  一:在Java中存在兩種繫結方式,一種為靜態繫結,又稱作早期繫結。另一種就是動態繫結,亦稱為後期繫結。

在處理java類中的成員變數時,並不是採用執行時繫結,而是一般意義上的靜態繫結。所以在向上轉型的情況下,物件的方法可以找到子類,而物件的屬性還是父類的屬性。


  區別對比:

(1)靜態繫結發生在編譯時期,動態繫結發生在執行時

    (2)使用private或static或final修飾的變數或者方法,使用靜態繫結(其他的方法全部為動態繫結)。而虛方法(可以被子類重寫的方法)則會根據執行時的物件進行動態繫結。

    (3)靜態繫結使用類資訊來完成,而動態繫結則需要使用物件資訊來完成。

    (4)過載(Overload)的方法使用靜態繫結完成,而重寫(Override)的方法則使用動態繫結完成。

     二:Java 技術安全模式要求在子類執行任何東西之前,描述父類的一個物件的各個方面都必須初始化。因此,Java 程式語言總是在執行子構造方法前呼叫父類構造方法的版本。有繼承的類在執行的時候,一定要記得:初始化子類必先初始化父類,

這是Java 程式的一個基本執行過程

     

 上述類的基本執行順序是:

  1. 先執行到第 8 行,這是程式的入口。
  2. 然後執行到第 9 行,這裡要 new 一個 Test,就要呼叫 Test 的構造方法。
  3. 就執行到第 4 行,注意:初始化子類必先初始化父類。
  4. 要先初始化父類,所以執行到第 15 行。
  5. 然後是第 14 行,初始化一個類,必須先初始化它的屬性。
  6. 然後是第 16 行。
  7. 然後是第 17 行,表示父類初始化完成。
  8. 然後是回到子類,開始初始化屬性,因此執行到第 2 行,然後是第 3 行。
  9. 子類屬性初始化完過後,才回到子類的構造方法,執行裡面的程式碼,也就是第 5、6 行。
  10. 然後是第7 行,表示 new 一個 Test 例項完成。
  11. 然後回到 main 方法中執行第 10 行。
  12. 然後是第 11 行。

  (2)宣告父類的引用,執行的過程中呼叫的是子類的物件,程式首先尋找子類物件的method方法,但如果沒有找到,於是向上轉型去父類尋找

     

    上例:由於子類重寫了父類的method方法,根據上面的理論知道會去呼叫子類的getName方法去執行,因為子類物件有getName方法而沒有向上轉型去尋找

     在處理java類中的成員變數時,並不是採用執行時繫結,而是一般意義上的靜態繫結。所以在向上轉型的情況下,物件的方法可以找到子類,而物件的屬性還是父類的屬性。 

   現在試圖呼叫子類的成員變數age,該怎麼做?最簡單的辦法是將該成員變數封裝成方法getter形式。

     

     三:Java繼承機制的初始化順序

      

     結果:

     

     執行順序是:  父類的靜態變數<=>父類的靜態塊->子類的靜態變數<=>子類的靜態

塊(靜態變數和靜態塊執行順序是以它們在程式裡出現的先後順序來順序執行的)

->(父類的例項化變數->父類的例項化塊->)父類的建構函式

->(子類的例項化變數->子類的例項化塊->)子類的建構函式

注:(1)靜態區塊的程式碼再類載入後初始化的時候執行,只執行一次;

(2)程式碼塊(未使用static宣告)在類例項化的時候執行;