Java程序員的日常 —— Java類加載中的順序


之前說過Java中類的加載順序,這次看完繼承部分,就結合繼承再來說說類的加載順序。

繼承的加載順序

由於static塊會在首次加載類的時候執行,因此下面的例子就是用static塊來測試類的加載順序。

package xing.test.thinking.chap7;
class A{
	static{
		System.out.println("A static");
	}
}
class B extends A{
	static{
		System.out.println("B static");
	}
}
class C extends B{
	private static D d = new D();
	static{
		System.out.println("C static");
	}
}
class D{
	static{
		System.out.println("D static");
	}
}
public class ExtendTest {
	public static void main(String[] args) {
		C c = new C();
	}
}

在上面的例子中,類C繼承B,B繼承A,而C有依賴於D。因此當創建C的時候,會自動加載C繼承的B和依賴的D,然后B又會加載繼承的A。只有A加載完,才能順利的加載B;BD加載完,才能加載C。這就是類的加載順序了。

A static
B static
D static
C static

所有的變量初始化完,才會執行構造方法

在類的加載過程中,只有內部的變量創建完,才會去執行這個類的構造方法。

package xing.test.thinking.chap7;
class A2{
	B2 b2 = new B2();
	static{
		System.out.println("A static");
	}
	public A2() {
		System.out.println("A2()");
	}
}
class B2{
	C2 c2 = new C2();
	D2 d2 = new D2();
	static{
		System.out.println("B static");
	}
	public B2() {
		System.out.println("B2()");
	}
}
class C2{
	static{
		System.out.println("C static");
	}
	public C2() {
		System.out.println("C2()");
	}
}
class D2{
	static{
		System.out.println("D static");
	}
	public D2() {
		System.out.println("D2()");
	}
}
public class VarTest {
	public static void main(String[] args) {
		A2 a2 = new A2();
	}
}

在上面的例子中,A2里面有B2變量,B2則有C2D2變量。因此類的加載還是先讀取到哪個,就執行相應的靜態塊。
當依賴的對象都定義完,才會執行構造方法:

A static
B static
C static
C2()
D static
D2()
B2()
A2()

靜態成員與普通成員類的加載區別

在類的加載過程中,靜態成員類的對象,會優先加載;而普通成員類的對象則是使用的時候才回去加載。

package xing.test.thinking.chap7;
class A3{
	B3 b3 = new B3();
	static C3 c4 = new C3();
	static{
		System.out.println("A3");
	}
}
class B3{
	static{
		System.out.println("B3");
	}
}
class C3{
	static{
		System.out.println("C3");
	}
}
public class StaticTest {
	public static void main(String[] args) {
		A3 a3 = new A3();
	}
}

輸出:

C3
A3
B3

總結

第一點,所有的類都會優先加載基類
第二點,靜態成員的初始化優先
第三點,成員初始化后,才會執行構造方法
第四點,靜態成員的初始化與靜態塊的執行,發生在類加載的時候。
第四點,類對象的創建以及靜態塊的訪問,都會觸發類的加載。

補充類構造方法的順序

看代碼:

package xing.test.thinking.chap8;
class A{
	public A() {
		System.out.println("A");
	}
}
class B extends A{
	public B() {
		System.out.println("B");
	}
}
class C extends B {
	private D d1 = new D("d1");
	private D d2 = new D("d2");
	public C() {
		System.out.println("C");
	}
}
class D {
	public D(String str) {
		System.out.println("D "+str);
	}
}
public class ExtendTest {
	public static void main(String[] args) {
		C c = new C();
	}
}

執行結果:

A
B
D d1
D d2
C

因此可以得出結論:

  • 首先會調用基類的構造方法
  • 其次,調用成員的構造方法
  • 最后,調用自己的構造方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM