類初始化(),類實例化()和方法重寫(override)的理解

考點:

對類初始化(<clinit>()),類實例化(<init>())和方法重寫(override)的理解。

題目:

main方法的輸出結果是什麼?

/*
 * 父類的初始化<clinit>:
 * (1)j = method();
 * (2)父類的靜態代碼塊
 * 
 *  父類的實例化方法:
 * (1)super()(最前)
 * (2)i = test();
 * (3)父類的非靜態代碼塊
 * (4)父類的無參構造(最後)
 * 
 * 非靜態方法前面其實有一個默認的對象this
 * this在構造器(或<init>)它表示的是正在創建的對象,因爲這裏是在創建Son對象,所以
 * test()執行的是子類重寫的代碼(面向對象多態)
 * 
 * 這裏i=test()執行的是子類重寫的test()方法
 */
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;
	}
}
/*
 * 子類的初始化<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)
 */
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();
	}
}

分析:

一個類要創建實例,首先要加載和初始化該類

1、main方法所在的類需要先加載和初始化
2、子類初始化之前要先執行父類,一個類的初始化就是<clinit>()方法()
3、初始化的內容:static靜態,按順序初始化即(5)(1)(10)(6)

下一步就是創建實例,創建實例需要對實例初始化:

前方高能預警------->

1、實例初始化就是執行<init>()方法。
2、<init>()方法可能有多個,有幾個構造器就有幾個<init>()方法。
3、<init>()方法由(1)非靜態實例變量,(2)非靜態代碼塊,(3)對應構造器代碼組成。
4、<init>()方法的首行是super(),即對應父類的<init>()方法。
5、super一定第一個執行,對應構造器一定最後執行,其它兩個按照代碼的順序執行。


根據上面的步驟,先執行的是super(),也就是對應父類的<init>
    先執行父類的super,沒有輸出
    然後執行父類的private int i = test();
    按理說改輸出(4)的,但是子類對test()這個方法重寫了,
        所以需要執行的test()方法是子類的test方法,而非父類的test()方法。
        所以輸出了(9)
    然後執行父類的{
		System.out.print("(3)");
	}
        輸出(3)
    最後是父類的構造器
        Father(){
		System.out.print("(2)");
	}
    輸出(2)
    至此,父類的<init>()方法執行完了,也就是子類的super()執行完了。
然後該執行子類的private int i = test();
    輸出(9)
然後執行子類的{
		System.out.print("(8)");
	}
    輸出(8)
最後執行子類的無參構造
    Son(){
		System.out.print("(7)");
	}
    輸出(7)

最終的結果是:(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)---(9)(3)(2)(9)(8)(7)

如果對上述的分析還是不理解,就再做一題!


public class Father{
	private static int j = method();
	
	static{
		System.out.print("(1)");
	}
	Father(){
		System.out.print("(2)");
	}
	{
		System.out.print("(3)");
	}
	private int i = test();
	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();
	}
}

答案是:(5)(1)(10)(6)(3)(9)(2)(9)(8)(7)---(3)(9)(2)(9)(8)(7)

你會發現(9)(3)換了位置,這就是之前所說的順序問題:

5、super一定第一個執行,對應構造器一定最後執行,其它兩個按照代碼的順序執行。

針對方法的重寫Override

哪些方法不能被重寫?
    1、final
    2、private
    3、靜態方法

哪些方法能被重寫?
    除了上述的情況,剩下的都能被重寫!

 

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