java變數,初始化快,建構函式的執行順序
對於JAVA中類的初始化是一個很基礎的問題,其中的一些問題也是易被學習者所忽略。當在編寫程式碼的時候碰到時,常被這些問題引發的錯誤,感覺莫名其妙。而且現在許多大公司的面試題,對於這方面的考查也是屢試不爽。不管基於什麼原因,我認為,對於java類中的初始化問題,有必要深入的瞭解。Java類的初始化,其實就是它在JVM的初始化問題(類載入的問題),對於它在JVM中的初始化是一個相當複雜的問題,是給專家們來探討的,所以在這裡我只是對一些容易忽略的問題,發表一下個人觀點:
1,在一個類的內部(不考慮它是另一個類的派生類):很多人認為,類的成員變數是在構造方法呼叫之後再初始化的,先不考慮這種觀點的正確性,先看一下下面的程式碼:
通過輸出,可見當生成Test02的例項test時,它並不是首先呼叫其構造方法而是先是成員變數的初始化,而且成員的初始化的順序以成員變數的定義順序有關,先定義的先初始化,初始化後再呼叫構造方法。其實成員變數的初始化,在類的所有方法呼叫之前進行,包括構造方法
當類中有Static 修飾的成員呢?測試下面一段程式碼:
可見static的成員比普通的成員變數先初始化。
我們都知道,如果一個類的成員變數沒有在定義時,系統會給予系統預設的值,有=號的就直接給予右值,系統在給予初值和=號給予值這2中方式,在執行時間上有先後嗎?為了測試,我編寫了如下程式碼:
為什麼是2和3呢?其實程式碼的執行順序是這樣的:首先執行給t1,i1,i2分別給予初始值null,0,0,再執行
Test04 t1 =new Test04(),這樣i1++,i2++被執行,i1,i2都變為1,執行完畢後接著執行int i1; i1,i2的值仍然是1,1,當執行int i2 = 2時i2被賦予了值,即i1 = 1,i2=2;再執行Test04 t2 = new Test04(),i1,i2再執行++,此時i1 =2,i2 =3,輸出i1,i2,結果就是:t2.i1 = 2,t2.i2 = 3。 通過上面的程式碼我們可以認為系統預設值的給予比通過等號的賦予先執行。
2,一個類還有上層的類,即父類:
當生成一個子類時,大家到知道會呼叫父類的構造方法。如果子類和父類中都有Static的成員變數呢,其實我們在深入分析一個類的內部初始化後,對於存在父類的類的初始化其實原理都一樣,具體以下面的程式碼為例:
可見當父類,和子類有Static時,先初始化Static,再初始化子類的Static,再初始化父類的其他成員變數->父類構造方法->子類其他成員變數->子類的構造方法。
父類上層還有父類時,總是先執行最頂層父類的Static-->派生類Static-->派生類Static-->.......-->子類Static-->頂層父類的其他成員變數-->父類構造方法--> 派生類的其他成員變數 --> 派生類構造方法--> ...............-->子類其他成員變數-->子類構造方法
討論到繼承,就不得提一下多型:
如果父類構造方法的程式碼中有子類中被重寫得方法,當執行這樣的語句
SuperClass super = new SubClass();
初始化時呼叫父類的構造方法,是執行父類的原方法,還是執行子類中被重寫的方法呢?
下面需要說明的一點也是至關重要的一點:那就是成員變數的初始化和非static初始化塊之間的執行順序是按照他們出現的先後順序來執行的