1. 程式人生 > >類初始化、例項初始化、方法重寫

類初始化、例項初始化、方法重寫

類初始化過程

一個類要建立例項需要先載入並初始化該類

  • main方法所在的類需要先載入和初始化

一個子類要初始化需要先初始化父類

一個類初始化就是執行<clinit>()方法

  • <clinit>()方法由靜態類變數顯式賦值程式碼和靜態程式碼塊組成
  • 類變數顯式賦值程式碼和靜態程式碼塊程式碼從上到下順序執行
  • <clinit>()方法只執行一次

例項初始化過程

例項初始化就是執行<init>()方法

  • <init>()方法可能過載有多個,有幾個構造器就有幾個<init
    >方法
  • <init>()方法由非靜態例項變數顯示賦值程式碼和非靜態程式碼塊、對應構造器程式碼組成
  • 非靜態例項變數顯示賦值程式碼和非靜態程式碼塊程式碼從上到下順序執行,而對應構造器的程式碼最後執行
  • 每次建立例項物件,呼叫對應構造器,執行的就是對應的<init>方法
  • <init>方法的首行是super()super(實參列表),即對應父類的<init>方法

方法的重寫Override

哪些方法不可以被重寫

  • final方法
  • 靜態方法
  • private等子類中不可見方法

物件的多型性

  • 子類如果重寫了父類的方法,通過子類物件呼叫的一定是子類重寫過的程式碼
  • 非靜態方法預設的呼叫物件是this
  • this物件在構造器或者說<init>方法中就是正在建立的物件
/**
 * 父類
 * @author BarryLee
 * @2018年11月10日@下午3:52:33
 */
public class Father {
	private int i = test();
	private static int j = method();
	static {
		System.out.print("(1)");
	}
	public 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;
	}
}
/**
 * 子類
 * @author BarryLee
 * @2018年11月10日@下午3:55:23
 */
public class Son extends Father{
	private int i = test();
	private static int j = method();
	static {
		System.out.print("[6]");
	}
	public 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;
	}
	///////////////----測試1----////////////////
	/*
	 * 測試類初始化
	 */
	@Test
	public void test1() {   
		// (5)(1)[10][6][9](3)(2)[9][8][7]
		// 相比main多了[9](3)(2)[9][8][7]是因為@Test是類反射,呼叫了空參構造方法
	}
	/*public static void main(String[] args) {
		// (5)(1)[10][6]
	}*/
	
	///////////////----測試2----////////////////
	/*
	 * 測試例項初始化、方法重寫
	 */
	@Test
	public void test2() {
		Son son1 = new Son();
		System.out.println("\r\n----");
		Son son2 = new Son();
		/*
			(5)(1)[10][6][9](3)(2)[9][8][7][9](3)(2)[9][8][7]
			----
			[9](3)(2)[9][8][7]
		 */
	}
	public static void main(String[] args) {
		Son son1 = new Son();
		System.out.println("\r\n----");
		Son son2 = new Son();
		/*
		 	(5)(1)[10][6][9](3)(2)[9][8][7]
			----
			[9](3)(2)[9][8][7]
		 */
	}
}

最後總結一下:

  • 父類靜態-子類靜態-父類成員變數-父類普通程式碼塊-父類構造-子類成員變數-子類普通程式碼塊-子類構造
  • 先靜態,再非靜態,先父類,再子類
  • 上邊所說的的 ”靜態“ 包括了成員變數和靜態程式碼塊
  • 非靜態的方法還會存在覆蓋的情況