代碼塊包括靜態代碼塊和非靜態代碼塊,另外還有構造函數,它們的執行順序是面試中經常考的,理解了下面這些基本知識,特麼再也不會做錯了。
一、靜態代碼塊
定義
一個類的源文件(.java)被編譯爲字節碼文件(.class)後,當需要使用某個類時,Java 虛擬機就將該類的字節碼文件讀入內存,加載類中的信息,靜態代碼塊只被執行一次,且靜態代碼塊不能被訪問修飾符(private、default、protected、public)修飾。靜態代碼塊是初始化該類的,而構造函數纔是初始化該類具體的對象實例的。
// 靜態代碼塊 static { ... }
靜態代碼塊執行的時機
1、顯式使用 Class.forName() 加載某個類時。
2、執行一個類的 main() 方法時。
3、使用構造函數創建(new)一個對象時,如 Test test = new Test(),等同於 Test test = Class.forName().newInstance()。
4、調用類的靜態變量(static)時,注意調用靜態常量(final static 關鍵字修飾)是不會執行靜態代碼塊的。
5、調用類的靜態函數時,無論是否有 final 關鍵字修飾,都會執行靜態代碼塊。
注意:
1、多個靜態代碼塊按定義的順序從前往後依次執行。
2、使用 Class.forName() 時不初始化該類不會執行靜態代碼塊,如 Class.forName("Test", false, Test.class.getClassLoader())。
靜態代碼塊的作用
靜態代碼塊具有初始化靜態成員變量和給靜態成員變量賦值的作用,如單例模式中的餓漢模式,類一旦加載就實例化出一個對象,用到的就是靜態代碼塊。
二、非靜態代碼塊
定義
非靜態代碼塊又稱爲初始化塊,直接用 {} 定義,可以用在類中和方法中。
// 非靜態代碼塊 { ... }
非靜態代碼塊執行的時機
靜態代碼塊執行之後,構造函數執行之前,每一次創建對象時執行。
注意:多個非靜態代碼塊按定義的順序從前往後依次執行。
非靜態代碼塊的作用
非靜態代碼塊也有初始化變量和對象的作用,但這個初始化有些雞肋,因爲我們都是在構造函數中初始化對象的。
三、總結
一個類中,按照如下順序執行:
1、執行靜態代碼塊
2、執行非靜態代碼塊
3、執行構造函數
對於靜態變量、靜態代碼塊、變量、非靜態代碼塊、構造函數,它們的初始化順序依次是(靜態變量、靜態初始化塊)>(變量、非靜態代碼塊)> 構造函數。
在多個類的繼承中,按照如下順序執行:
1、執行父類的靜態代碼塊,初始化父類靜態變量。
2、執行子類的靜態代碼塊,初始化子類靜態變量。
3、執行父類的非靜態代碼塊和父類的構造函數,初始化父類的成員變量。
3、執行子類的非靜態代碼塊和字類的構造函數,初始化子類的成員變量。
初始化過程