天天看點

javaSE初始化順序的考題

問題:以下代碼的運作結果是什麼?某大廠的面試題

有一個父類:

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(){
//		super();//寫或不寫都在,在子類構造器中一定會調用父類的構造器
		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();
	}
}
           

運作結果是什麼呢?

我們先分析一下,有基礎的同學應該知道類的初始化順序,在這個基礎上,我們就知道了結果:

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

(9)(3)(2)(9)(8)(7)

分析:

/*
 * 父類的初始化<clinit>:
 * (1)j = method();
 * (2)父類的靜态代碼塊
 * 
 *  父類的執行個體化方法:
 * (1)super()(最前)
 * (2)i = test();
 * (3)父類的非靜态代碼塊
 * (4)父類的無參構造(最後)
 * 
 * 非靜态方法前面其實有一個預設的對象this
 * this在構造器(或<init>)它表示的是正在建立的對象,因為這裡是在建立Son對象,是以
 * test()執行的是子類重寫的代碼(面向對象多态)
 * 
 * 這裡i=test()執行的是子類重寫的test()方法
 */
           
/*
 * 子類的初始化<clinit>:
 * (1)j = method();
 * (2)子類的靜态代碼塊
 * 
 * 先初始化父類:(5)(1)
 * 初始化子類:(10)(6)
 * 
 * 子類的執行個體化方法<init>:
 * (1)super()(最前)      (9)(3)(2)
 * (2)i = test();    (9)
 * (3)子類的非靜态代碼塊    (8)
 * (4)子類的無參構造(最後) (7)
 * 
 * 因為建立了兩個Son對象,是以執行個體化方法<init>執行兩次
 * 
 * (9)(3)(2)(9)(8)(7)
 */
           

子類的super代表父類的整個執行個體化方法

為什麼不會出現(4)?

因為方法的重寫問題

父類的執行個體方法走到第2步時,由于初始化的是子類,是以會調用子類的test()方法

建立了兩個Son對象,是以執行個體初始化方法執行了兩次

哪些方法不能被重寫:

final方法

靜态方法

private等子類中不可見的方法

靜态變量與靜态代碼塊是順序執行的

非靜态變量與非靜态代碼塊也是順序執行的

構造函數總是最後執行