java中帶繼承類的載入順序詳解及實戰

阿豪聊乾貨發表於2016-05-12

一、背景:

  在面試中,在java基礎方面,類的載入順序經常被問及,很多時候我們是搞不清楚到底類的載入順序是怎麼樣的,那麼今天我們就來看看帶有繼承的類的載入順序到底是怎麼一回事?在此記下也方便以後複習鞏固!

二、測試步驟:

1.父類程式碼

 1 package com.hafiz.zhang;
 2 
 3 public class Fu
 4 {
 5     private int i = print("this is father common variable");
 6     private static int j = print("this is father static variable");
 7     static{
 8         System.out.println("this is father static code block");
 9     }
10     {
11         System.out.println("this is father common code block");
12     }
13     public Fu(){
14         System.out.println("this is father constructor");
15     }
16 
17     static int print(String str){
18         System.out.println(str);
19         return 2;
20     }
21 }

2.子類程式碼

 1 package com.hafiz.zhang;
 2 
 3 public class Zi extends Fu
 4 {
 5     private int l = print("this is son common variable");
 6     private static int m = print("this is son stati variable");
 7     static{
 8         System.out.println("this is son static code block");
 9     }
10     {
11         System.out.println("this is son common code block");
12     }
13     public Zi(){
14         System.out.println("this is son constructor");
15     }
16     public static void main(String[] args) {
17         new Zi();    
18     }
19 }

最後執行結果為:

下面讓我們修改一下兩個類中靜態程式碼塊和靜態成員變數的位置並重新執行

3.修改後的父類程式碼

 1 package com.hafiz.zhang;
 2 
 3 public class Fu
 4 {
 5     static{
 6         System.out.println("this is father static code block");
 7     }
 8     {
 9         System.out.println("this is father common code block");
10     }
11     public Fu(){
12         System.out.println("this is father constructor");
13     }
14 
15     static int print(String str){
16         System.out.println(str);
17         return 2;
18     }
19     private int i = print("this is father common variable");
20     private static int j = print("this is father static variable");
21 }

4.修改後的子類程式碼

 1 package com.hafiz.zhang;
 2 
 3 public class Zi extends Fu
 4 {
 5     static{
 6         System.out.println("this is son static code block");
 7     }
 8     {
 9         System.out.println("this is son common code block");
10     }
11     public Zi(){
12         System.out.println("this is son constructor");
13     }
14     public static void main(String[] args) {
15         new Zi();    
16     }
17     private int l = print("this is son common variable");
18     private static int m = print("this is son stati variable");
19 }

修改後的執行結果:

三、測試結果

由測試結果可知:程式首先載入類,然後再對類進行初始化。

載入類的順序為:先載入基類,基類載入完畢後再載入子類。

初始化的順序為:先初始化基類,基類初始化完畢後再初始化子類。

最後得出類載入順序為:先按照宣告順序初始化基類靜態變數和靜態程式碼塊,接著按照宣告順序初始化子類靜態變數和靜態程式碼塊,而後按照宣告順序初始化基類普通變數和普通程式碼塊,然後執行基類建構函式,接著按照宣告順序初始化子類普通變數和普通程式碼塊,最後執行子類建構函式。

對於本測試中的執行順序為:先初始化static的變數,在執行main()方法之前就需要進行載入。再執行main方法,如果new一個物件,則先對這個物件類的基本成員變數進行初始化(非方法),包括構造程式碼塊,這兩種是按照編寫順序按序執行的,再呼叫建構函式。 關於繼承的初始化機制,首先執行含有main方法的類,觀察到Zi類含有基類Fu,即先載入Fu類的static變數,再載入Zi類的static變數。載入完static變數之後,呼叫main()方法,new Zi()則先初始化基類的基本變數和構造程式碼塊,再呼叫基類的構造方法。然後再初始化子類Zi的基本變數和構造程式碼塊,再執行子類的建構函式。

相關文章