java程式執行順序理解
public class StaticTest { public static int k = 0; public static StaticTest t1 = new StaticTest("t1"); public static StaticTest t2 = new StaticTest("t2"); public static int i = print("i"); public static int n = 99; public int j = print("j"); { print("構造塊"); } static { print("靜態塊"); } public StaticTest(String str) { System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++n; ++i; } public static int print(String str) { System.out.println((++k) + ":" + str + " i=" + i + "n=" + n); ++i; return ++n; } public static void main(String[] args) { StaticTest t = new StaticTest("init"); } }
1. 首先載入類,載入類過程中對於定義的靜態欄位分配記憶體空間,也是在方法區中,並進行零初始化,即數字型別初始化為0,boolean初始化為false,引用型別初始化為null等。這也就是為什麼剛開始i=0,n=0
2. 執行第一句public static int
3. 執行第二句public static StaticTest t1 = new StaticTest("t1");這是定義了一個類的靜態物件,在t1物件初始化時先執行非靜態方法或者非靜態常量,順序執行,接著執行構造引數。意思是當聲明瞭物件名後,我的類有了一個物件,就預設呼叫了類中定義的非靜態的變數 和方法,依次進行;所以這時就會呼叫public int j = print("j");
此時會呼叫print方法,其中++i,i=1=i+1; 返回值++n,n=1=n+1;j=1,k=1.
列印 1:j i=0 n=0;
然後執行非靜態塊print("構造塊");呼叫print函式
列印 2:構造塊 i=1 n=1
沒有了非靜態的方法,塊或常量後,之後會對t1初始化,執行類的建構函式public StaticTest(String str);
列印 3:t1 i=2 n=2
4. 執行第三句public static StaticTest t2 = new StaticTest("t2");和上面一步的分析方法一樣。
依次列印
4:j i=3 n=3
5:構造塊 i=4 n=4
6:t2 i=5 n=5
5. 執行第四句public static int i = print("i");呼叫print方法
列印 7:i i=6 n=6
6. 執行第五句public static int n = 99;至此靜態變數載入完畢,然後載入靜態塊和靜態方法的宣告,只有當呼叫靜態方法時才執行靜態方法的內容。
7. 執行第六句static{ print("靜態塊"); } 所以呼叫print函式
列印 8:靜態塊 i=7 n=99 由於n在上一步初始化了。
8. 執行main函式體StaticTest t = new StaticTest("init");同樣分析思路和第3步是一樣的,當聲明瞭物件t時,程式會先執行非靜態塊和變數以及非靜態方法的宣告。然後執行類物件的初始化。所以先執行public int j = print("j");呼叫了print函式
列印 9:j i=8 n=100
然後執行非靜態塊print("構造塊");呼叫了print函式
列印 10:構造塊 i=9 n=101
最後執行物件的初始化,呼叫了建構函式public StaticTest(String str);
列印 11:init i=10 n=102
程式的入口函式依然是main函式,這裡的知識點在於程式時類的載入過程和java虛擬機器的記憶體分配。程式執行的順序是,java虛擬機器載入由.java編譯生成出的.class位元組碼檔案,將其載入至記憶體,然後找到了main函式,但並不是執行main函式的第一句,而是載入類的資料,當載入一個類時,JVM會根據屬性的資料型別第一時間賦預設值(一舉生成的),即數字型別初始化為0,boolean初始化為false,引用型別初始化為null等。然後再進行靜態屬性初始化,併為靜態屬性分配記憶體空間,靜態方法的宣告,靜態塊的載入,沒有優先順序之分,按出現順序執行,靜態部分僅僅載入一次。至此為止,必要的類都已經載入完畢,物件就可以被建立了。
當物件被建立時,就會呼叫類的動態屬性,普通方法宣告,構造塊。最後在呼叫建構函式。
中的來說呼叫過程如下:
先載入類的靜態屬性(變數),靜態塊,靜態方法的宣告。
然後當定義了類的物件時,呼叫非靜態屬性(變數),構造塊,普通方法宣告。