阿里面試題——Java物件初始化
Java物件初始化
這是一道阿里巴巴的關於Java物件初始化的面試題,堪稱經典,程式碼很簡單(編寫格式做了些修改),但是需要面試者對Java中物件初始化有一個透徹的認識,那麼通過這道面試題,對我有點啟發,所以希望在這裡分享給大家,希望能給迷惘的初學者一起指引,下面我們直入主題,先看看程式碼:
public class InitializeDemo { private static int k = 1; private static InitializeDemo t1 = new InitializeDemo("t1"); private static InitializeDemo t2 = new InitializeDemo("t2"); private static int i = print("i"); private static int n = 99; static { print("靜態塊"); } private int j = print("j"); { print("構造塊"); } public InitializeDemo(String str) { System.out.println((k++) + ":" + str + "i=" + i + "n=" + n); ++i; ++n; } public static int print(String str) { System.out.println((k++) + ":" + str + "i=" + i + "n=" + n); ++n; return ++i; } public static void main(String args[]) { new InitializeDemo("init"); } }
做些小補充,這也是很多Java學習者最初都能接觸到的一些但是不是很理解的概念:
核心理念:
- 靜態屬性和靜態程式碼塊都是在類載入的時候初始化和執行,兩者的優先級別是一致的,且高於非靜態成員,執行按照編碼順序。
- 非靜態屬性和匿名構造器在所有的構造方法之前執行,兩者的優先級別一致,執行按照編碼順序。
- 以上執行完畢後執行構造方法中的程式碼。
讀者仔細揣摩上面三條句子,也就是Java物件初始化的順序,也就明白以上程式的輸出結果為什麼如下:
ji=0n=0 構造塊i=1n=1 t1i=2n=2 ji=3n=3 構造塊i=4n=4 t2i=5n=5 ii=6n=6 靜態塊i=7n=99 ji=8n=100 構造塊i=9n=101 initi=10n=102
如果還是沒有明白,就看下面詳解,一下詳解的順序就是按照上文的核心理念的順序來執行的(建議讀者把自己帶入JVN的世界裡,跟著JVM一步一步往下面走):
- 執行main方法的時候,JVM會呼叫ClassLoader來載入InitializeDemo類,那麼一起源於這次載入。
- 上面有四個靜態屬性,所以會按順序逐一初始化這四個靜態屬性。
- private static int k = 1; 此時將k初始化為1。
-
private static InitializeDemo t1 = new InitializeDemo("t1");建立InitializeDemo物件,那麼按照核心理念中的順序,先執行private int j = print("j");,打印出j,然後執行構造
塊,最後執行構造方法。
5.private static InitializeDemo t2 = new InitializeDemo("t2");同步驟4。
6.private static int i = print("i");列印i。
7.private static int n = 99;直到這一步,n才被賦值為99,之前是從預設的0開始++的。
8.靜態屬性初始化完畢,程式碼走到靜態塊,打印出靜態塊,此時n=99。
9.靜態屬性和靜態塊執行完畢,然後執行main方法中的程式碼new InitializeDemo("init");
10.main方法中建立物件,先初始化非靜態屬性,private int j = print("j");列印j,然後執行構造塊,最後執行構造方法。
不知道我解說清楚了沒有,只要把握住核心理念,碰到在複雜的問題也都不會怕了。
用一個公式概括一下Java物件初始化執行優先級別:
(靜態屬性=靜態程式碼塊)> (非靜態屬性 = 構造塊)> 構造方法
總結一下核心理念:
- 靜態只在類載入的時候執行,且執行一次。
- 非靜態只在例項化的時候執行,且每次例項化都執行。
- 靜態在非靜態之前執行。
- 靜態屬性和靜態塊的執行順序取決於編碼順序,對它們一視同仁。
- 非靜態屬性和構造塊的執行順取決於編碼順序,對它們也一視同仁。
- 最後執行構造方法。
上面的總結有點繞對吧,問題進一步簡化的話,就更好理解了:
讀者將靜態程式碼塊視為一個靜態屬性,將構造塊視為一個非靜態屬性,那麼問題簡化到了這種路線“靜態屬性-->非靜態屬性-->構造方法“
不積跬步無以至千里,祝願大家學習進步,樂於分享~ ~