原來自己一直都沒弄明白Java程序的執行順序問題,今天,自己寫了個測試,果然與自己考慮的有差距
測試代碼:
一個父類Animal

一個子類Dog

測試類Test

運行結果:

所以執行順序是:
父類Animal靜態代碼塊->子類Dog靜態代碼塊->父類Animal非靜態代碼塊->父類Animal構造函數->子類Dog非靜態代碼塊->子類Dog構造函數
探索:為啥是這樣的執行順序
我們首先來看如果不使用繼承會是怎樣的結果:

靜態代碼塊-->非靜態代碼塊-->構造函數
靜態代碼塊,隨着類的加載而執行,只執行一次,並優先於主函數執行,是對類初始化的。
非靜態代碼塊,作用:給所有對象進行初始化。
對象一建立就運行,而且優先於構造函數執行。
代碼塊是給所有對象進行統一初始化,
而構造函數是給對應的對象初始化。
代碼塊中定義的是不同對象共性的初始化內容。
我們再來看繼承之后的,
1.Test中main方法內的new會觸發JVM對類的加載,因為Dog是繼承了Animal的,所以,先加載Animal,
執行所有的static域的初始化語句或者初始化塊(按出現的順序),此時Animal內static塊的打印語句執行了;
父類的方法表建立后算是父類加載完畢,接着會加載子類Dog,執行的過程與父類類似。因為子類沒有static的數據域,所以僅僅static的初始化塊內的打印語句執行;
(static的初始化只有一次,因為它僅僅在類加載的時候執行而與實例化沒有關系)
2.需要的類加載完畢之后new Dog()開始使用類構造器創建實例
執行父類的非靜態代碼塊,進行初始化,
然后執行父類構造器(super()...)
執行子類非靜態代碼塊
執行子類構造器
所以綜上所述,就會出現如下執行結果:

總結:靜態代碼塊總是最先執行。
非靜態代碼塊跟非靜態方法一樣,跟對象有關。只不過非靜態代碼塊在構造函數之前執行。
父類非靜態代碼塊、構造函數執行完畢后(相當於父類對象初始化完成), 才開始執行子類的非靜態代碼塊和構造函數
