Java類靜態屬性、靜態塊、非靜態屬性、非靜態塊、建構函式在初始化時的執行順序,java建構函式
前言 今天在看Android ContentProvider實現的時候,突然想到了Java類在new的過程中,靜態域、靜態塊、非靜態域、非靜態塊、建構函式的執行順序問題。其實這是一個很經典的問題,非常考察對Java基礎知識的掌握程度。很多面試過程中相信也有這樣的問題,趁著周末有時間複習一下。
結論 這裡先把整理好的結論拋給大家,然後我在寫個程式來驗證我們的結論。在Java類被new的過程中,執行順序如下: 在實現繼承的類被new的過程中,初始化執行順序如下: 這裡需要簡單的介紹一下靜態代碼塊和非靜態代碼塊。1. 靜態代碼塊:
static {}2. 非靜態代碼塊
{} 靜態代碼塊和非靜態代碼塊的異同點如下:
- 相同點:都是JVM載入類時且在建構函式執行之前執行,在類中都可以定義多個,一般在代碼塊中對一些static變數進行賦值。
- 不同點:靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊 > 非靜態代碼塊)。靜態代碼塊只在第一次new時執行一次,之後不再執行。而非靜態代碼塊每new一次就執行一次。
驗證 對於結論的最好驗證就是寫出代碼來進行結果證明。首先,來看一下無繼承的類初始化時的執行順序,代碼如下:
public class InitOderTest {public static String STATIC_FIELD = "靜態屬性";// 靜態塊static {System.out.println(STATIC_FIELD);System.out.println("靜態代碼塊");}public String field = "非靜態屬性";// 非靜態塊{System.out.println(field);System.out.println("非靜態代碼塊");}public InitOderTest() {System.out.println("無參建構函式");}public static void main(String[] args) {InitOderTest test = new InitOderTest();}} 執行結果:
靜態屬性靜態代碼塊非靜態屬性非靜態代碼塊無參建構函式
接下來,我們驗證一下,當Java類實現繼承後,執行順序是否和我們的結論吻合。測試代碼如下:
class ParentTest {public static String PARENT_STATIC_FIELD = "父類-靜態屬性";// 父類-靜態塊static {System.out.println(PARENT_STATIC_FIELD);System.out.println("父類-靜態代碼塊");}public static String parentField = "父類-非靜態屬性";// 父類-非靜態塊{System.out.println(parentField);System.out.println("父類-非靜態代碼塊");}public ParentTest() {System.out.println("父類—無參建構函式");}}public class InitOderTest extends ParentTest {public static String STATIC_FIELD = "靜態屬性";// 靜態塊static {System.out.println(STATIC_FIELD);System.out.println("靜態代碼塊");}public String field = "非靜態屬性";// 非靜態塊{System.out.println(field);System.out.println("非靜態代碼塊");}public InitOderTest() {System.out.println("無參建構函式");}public static void main(String[] args) {InitOderTest test = new InitOderTest();}} 執行結果如下:
父類-靜態屬性父類-靜態代碼塊靜態屬性靜態代碼塊父類-非靜態屬性父類-非靜態代碼塊父類—無參建構函式非靜態屬性非靜態代碼塊無參建構函式
通過程式驗證,可以看出我們的結論是準確的。