在Java中,有兩種初始化塊:靜态初始化塊和非靜态初始化塊。它們都是定義在類中,用大括号{}括起來,靜态代碼塊在大括号外還要加上static關鍵字。
非靜态初始化塊(構造代碼塊):
作用:給對象進行初始化。對象一建立就運作,且優先于構造函數的運作。
與構造函數的差別:非靜态初始化塊給所有對象進行統一初始化,構造函數隻給對應對象初始化。
應用:将所有構造函數共性的東西定義在構造代碼塊中。
- 對于普通的類而言,可以放在初始化塊中的初始化工作其實完全可以放到構造函數中進行,隻不過有時會帶來些許不便,如有多個構造器,就要在多個地方加上初始化函數完成初始化工作,而如果放到初始化塊中的話則隻要寫一次即可。
- 初始化塊真正展現其獨一無二的作用是在匿名内部類中。
- 由于是匿名内部類,因而無法寫構造方法,但是很多時候還是要完成相應的初始化工作,這時就需要用到初始化塊了,特别是Android中大量地使用匿名内部類,初始化塊的作用就十分突出
靜态初始化塊:
作用:給類進行初始化。随着類的加載而執行,且隻執行一次
與構造代碼塊的差別:
1)構造代碼塊用于初始化對象,每建立一個對象就會被執行一次;靜态代碼塊用于初始化類,随着類的加載而執行,不管建立幾個對象,都隻執行一次。
2)靜态代碼塊優先于構造代碼塊的執行
3)都定義在類中,一個帶static關鍵字,一個不帶static
比如可以記錄第一次通路類的日志,或友善單例模式的初始化等。對于單例模式,可以先用static塊初始化一些可能還被其他類通路的基礎參數,等到真正需要加載大量資源的時候(getInstance)再構造單體,在構造函數中加載資源。
構造函數、非靜态初始化塊、靜态代碼塊都是用于初始化,三者的執行順序依次是:靜态代碼塊>構造代碼塊>構造函數。
其實初始化塊就是構造器的補充,初始化塊是不能接收任何參數的,定義的一些所有對象共有的屬性、方法等内容時就可以用初始化塊初始化了。
靜态初始化塊的作用就是當JVM在裝載類時,你想讓它做一些事情,那麼,就可以用靜态初始化塊。這幾者的執行順序是:
(JVM在裝載類時)先裝載類的靜态成員,再執行靜态初始化塊(同樣,當一個類有繼承自某類時,則會先裝載該父類,那麼,父類的裝載或執行順序,也都如句子所述)。
(在建立類的執行個體時)先執行執行個體初始化塊,再執行構造方法;但對于一棵繼承樹中,會先調用父類的構造方法,那麼其執行順序也如句子所述。
執行順序
所有的靜态初始化塊都優先執行,其次才是非靜态的初始化塊和構造函數,它們的執行順序是:
- 父類的靜态初始化塊
- 子類的靜态初始化塊
- 父類的初始化塊
- 父類的構造函數
- 子類的初始化塊
- 子類的構造函數