深入理解Java中靜態初始化塊、初始化塊和構造方法

chi633發表於2017-12-21

在Java中,有兩種初始化塊:靜態初始化塊和非靜態初始化塊。它們都是定義在類中,用大括號{}括起來,靜態程式碼塊在大括號外還要加上static關鍵字。

非靜態初始化塊(構造程式碼塊):

作用:給物件進行初始化。物件一建立就執行,且優先於建構函式的執行。 與建構函式的區別:非靜態初始化塊給所有物件進行統一初始化,建構函式只給對應物件初始化。 應用:將所有建構函式共性的東西定義在構造程式碼塊中。

  • 對於普通的類而言,可以放在初始化塊中的初始化工作其實完全可以放到建構函式中進行,只不過有時會帶來些許不便,如有多個構造器,就要在多個地方加上初始化函式完成初始化工作,而如果放到初始化塊中的話則只要寫一次即可。
  • 但是,如果只是這一點便利的話,還不足以使用初始化塊,其實初始化塊真正體現其獨一無二的作用是在匿名內部類中,由於是匿名內部類,因而無法寫構造方法,但是很多時候還是要完成相應的初始化工作,這時就需要用到初始化塊了,特別是Android中大量地使用匿名內部類,初始化塊的作用就十分突出

靜態初始化塊:

作用:給類進行初始化。隨著類的載入而執行,且只執行一次 與構造程式碼塊的區別: 1)構造程式碼塊用於初始化物件,每建立一個物件就會被執行一次;靜態程式碼塊用於初始化類,隨著類的載入而執行,不管建立幾個物件,都只執行一次。 2)靜態程式碼塊優先於構造程式碼塊的執行 3)都定義在類中,一個帶static關鍵字,一個不帶static

比如可以記錄第一次訪問類的日誌,或方便單例模式的初始化等。對於單例模式,可以先用static塊初始化一些可能還被其他類訪問的基礎引數,等到真正需要載入大量資源的時候(getInstance)再構造單體,在建構函式中載入資源。

建構函式、非靜態初始化塊、靜態程式碼塊都是用於初始化,三者的執行順序依次是:靜態程式碼塊>構造程式碼塊>建構函式。 其實初始化塊就是構造器的補充,初始化塊是不能接收任何引數的,定義的一些所有物件共有的屬性、方法等內容時就可以用初始化塊初始化了。

靜態初始化塊的作用就是當JVM在裝載類時,你想讓它做一些事情,那麼,就可以用靜態初始化塊。這幾者的執行順序是:

(JVM在裝載類時)先裝載類的靜態成員,再執行靜態初始化塊(同樣,當一個類有繼承自某類時,則會先裝載該父類,那麼,父類的裝載或執行順序,也都如句子所述)。

(在建立類的例項時)先執行例項初始化塊,再執行構造方法;但對於一棵繼承樹中,會先呼叫父類的構造方法,那麼其執行順序也如句子所述。

執行順序

所有的靜態初始化塊都優先執行,其次才是非靜態的初始化塊和建構函式,它們的執行順序是:

  • 父類的靜態初始化塊
  • 子類的靜態初始化塊
  • 父類的初始化塊
  • 父類的建構函式
  • 子類的初始化塊
  • 子類的建構函式

相關文章