什麼時候會發生類初始化(類的主動引用和類的被動引用)

什麼時候會發生類初始化

前言

什麼時候會發生類初始化

類的主動引用

如果在main()方法中去new一個子類的對象(子類繼承了父類),那麼JVM會自動初始化父類
 
由於這裏是new子類(Son類),父類沒有被初始化,所以JVM會自動初始化父類先

練習代碼1(主動引用(new 的形式))
// 測試類什麼時候會初始化
public class Test05 {
	
	static {
		System.out.println("Main類被加載");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 1、主動引用
		// 由於這裏是new子類(Son類),父類沒有被初始化,所以JVM會自動初始化父類先
		Son son = new Son();
	}
}

class Father{
	
	static int b = 2;
	
	// 靜態代碼塊
	static {
		System.out.println("父類被加載");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子類被加載");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

運行結果:

Main類被加載
父類被加載
子類被加載
練習代碼2(主動引用(反射的形式))
// 測試類什麼時候會初始化
public class Test05 {
	
	static {
		System.out.println("Main類被加載");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 1、主動引用
		// 由於這裏是new子類(Son類),父類沒有被初始化,所以JVM會自動初始化父類先
//		Son son = new Son();
		
		// 反射也會產生主動引用
		Class.forName("com.lwm.reflection.Son");
	}
}

class Father{
	
	static int b = 2;
	
	// 靜態代碼塊
	static {
		System.out.println("父類被加載");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子類被加載");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

結果與上面的一致
 
通過反射也是會產生類的主動引用,它會把所有東西加載進來(Main類被加載、父類被加載、子類被加載),這樣會極大的消耗資源
 

類的被動引用

通過子類去調用父類的靜態方法或者靜態變量,不會對子類產生任何影響,子類不會被加載

練習代碼1(被動引用(通過子類去調用父類的靜態方法或者靜態變量))
// 測試類什麼時候會初始化
public class Test05 {
	
	static {
		System.out.println("Main類被加載");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 不會產生類的引用的方法
		
		// 通過子類去調用父類的靜態方法或者靜態變量,不會對子類產生任何影響,子類不會被加載
		System.out.println(Son.b);
	}
}

class Father{
	
	static int b = 2;
	
	// 靜態代碼塊
	static {
		System.out.println("父類被加載");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子類被加載");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

運行結果:

Main類被加載
父類被加載
2
練習代碼2(被動引用(通過數組形式))

數組佔了一個空間,開闢了5個空間(如果沒被加載說明什麼都沒幹(此時只有main類被加載))

// 測試類什麼時候會初始化
public class Test05 {
	
	static {
		System.out.println("Main類被加載");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 不會產生類的引用的方法
        
        // 通過一個數組
		// 數組佔了一個空間,開闢了5個空間(如果沒被加載說明什麼都沒幹(此時只有main類被加載))
		Son[] array = new Son[5];
	}
}

class Father{
	
	static int b = 2;
	
	// 靜態代碼塊
	static {
		System.out.println("父類被加載");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子類被加載");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

運行結果:

Main類被加載
爲什麼會加載Main類呢?

因爲當虛擬機啓動,就會先初始化main方法所在的類,然後才執行 Son[] array = new Son[5];這行代碼,這時沒有任何類被加載,這行代碼只是一個數組,它只是一個名字和一片空間而已

練習代碼3(被動引用(通過調用常量形式))
// 測試類什麼時候會初始化
public class Test05 {
	
	static {
		System.out.println("Main類被加載");
	}
	
	public static void main(String[] args) throws ClassNotFoundException {
		// 不會產生類的引用的方法
	
		// 調用子類的常量(常量並不會引起父類和子類的初始化)
		System.out.println(Son.M);
	}
}

class Father{
	
	static int b = 2;
	
	// 靜態代碼塊
	static {
		System.out.println("父類被加載");
	}
}

class Son extends Father{
	
	static {
		System.out.println("子類被加載");
		m = 300;
	}
	
	static int m = 100;
	static final int M = 1;
}

運行結果:

Main類被加載
1

所有的常量和類的靜態變量都是在鏈接階段就被賦了一個值,在鏈接階段就做了,初始化的時候就已經存在了

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