那些你還不熟悉的---類的初始化和實例化的初始化過程

面試題:
如下兩個類的代碼

/*父類對象*/
public class Father{
	private int i = test();
	private static int j = method();
	static{
		System.out.print("(1)");
	}

	Father(){
		System.out.print("(2)");
	}
	{
		System.out.print("(3)");
	}
	
	
	public int test(){
		System.out.print("(4)");
		return 1;
	}
	public static int method(){
		System.out.print("(5)");
		return 1;
	}
}
/*子類對象*/
public class Son extends Father{
	private int i = test();
	private static int j = method();
	static{
		System.out.print("(6)");
	}
	Son(){
		System.out.print("(7)");
	}
	{
		System.out.print("(8)");
	}
	public int test(){
		System.out.print("(9)");
		return 1;
	}
	public static int method(){
		System.out.print("(10)");
		return 1;
	}
	public static void main(String[] args) {
		Son s1 = new Son();
		System.out.println();
		Son s2 = new Son();
	}
}

問題:

  1. 執行Son類的main函數,控制檯打印的結果是什麼?
  2. 如果main方法什麼都不寫,控制檯打印的結果是什麼?

結果

第一題答案:

(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2)(9)(8)(7)

第二題答案:

(5)(1)(10)(6)

你是否答對了?

類的初始化過程

使用到一個類對其進行實例化就需要先對類進行初始化,而且類的初始化只執行一次!這個特點可以做單例模式
類的初始化就是將靜態成員變量靜態代碼塊進行初始化,靜態代碼塊和靜態成員變量的執行順序按照代碼的先後順序執行,誰在上面就誰先執行初始化!

注意:main方法所在的類先加載和初始化,該類的初始化又要先初始化父類

也就是說最先初始化的類是父類的靜態代碼塊或者靜態成員變量,然後是子類的靜態代碼塊或者靜態成員變量靜態代碼塊和靜態成員變量的先後順序由代碼先後順序影響

實例化的初始化過程

一個類要進行實例化,就需要先對類初始化然後再實例化,實例化又需要先實例化父類,後實例化子類
實例化需要初始化非靜態成員變量非靜態代碼塊,非static的成員變量和代碼塊的先後順序也是誰先聲明誰先執行。
最後執行構成方法

總結

整體的初始化排序
類初始化 > 實例化初始化


**父類**靜態成員變量 或 靜態代碼塊(順序由聲明先後順序定)>
**子類**靜態成員變量 或 靜態代碼塊(順序由聲明先後順序定)>
**父類**非靜態成員變量 或 非靜態代碼塊(順序由聲明先後順序定)>
父類構造方法>
**子類**非靜態成員變量 或 非靜態代碼塊(順序由聲明先後順序定)>
子類構造方法

如果以16進制的方式去查看編譯後的class文件會發現有<clinit>、<init>等方法
而<clinit>()就是進行類初始化執行的指令,裏面由 靜態類成員變量顯示賦值 和 靜態代碼塊 組成,裏面的順序按照聲明順序先後執行
<init>()可能有多個,因爲有無參構造器和有參構造器,有幾個構造器就有幾個<init>()。是執行示例化初始化的指令,裏面由 非靜態類成員變量顯示賦值 和 非靜態代碼塊 組成,裏面的順序按照聲明順序先後執行,<init>()首行一定是super();構造器裏的代碼最後執行。每一次實例化都執行一次<init>()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章