1. 程式人生 > >類的加載連接初始化順序 (二)

類的加載連接初始化順序 (二)

void string 字節碼 ole name 階段 face interface sna

1.數組對象的使用,不會導致對應類的初始化。

在創建 ClassName[]數組時,並不會創建對應對象,也不會初始化對應類,會創建一個編譯時類型 [+L+類全名 如下:

public class MyTest02 {

	public static void main(String[] args) {
		Sub[] subs = new Sub[1];
		Sub[][] subss = new Sub[1][1];
		String[] strs = new String[1];
		int[] is = new int[1];
		char[] chars = new char[1];
		byte[] bs = new byte[1];
		boolean[] bo = new boolean[1];
		System.out.println("Sub[]‘s class is       "+subs.getClass());
		System.out.println("Sub[][]‘s class is     "+subss.getClass());
		System.out.println("Sub[]‘s father‘s class "+subs.getClass().getSuperclass());
		System.out.println("String[]‘s class is    "+strs.getClass());
		System.out.println("int[]‘s class is       "+is.getClass());
		System.out.println("char[]‘s class is      "+chars.getClass());
		System.out.println("byte[]‘s class is      "+bs.getClass());
		System.out.println("boolean[]‘s class is   "+bo.getClass());
	}

}
class Sub{
	static {
		System.out.println("Sub static block");
	}
}
//~out:
Sub[]‘s class is       class [Ljvm.Sub;
Sub[][]‘s class is     class [[Ljvm.Sub;
Sub[]‘s father‘s class class java.lang.Object
String[]‘s class is    class [Ljava.lang.String;
int[]‘s class is       class [I
char[]‘s class is      class [C
byte[]‘s class is      class [B
boolean[]‘s class is   class [Z

 特別的 這些數組的父類為Object,二維數組則多加一個[符號。

2.初始化中各字段初始化的先後順序

關於類初始化的復制順序 如下代碼的輸出結果應該很好判斷

public class MyTest03 {

	public static void main(String[] args) {
		;
		System.out.println("Singleton.value1 = "+Singleton.getInstance().value1);
		System.out.println("Singleton.value2 = "+Singleton.getInstance().value2);

	}
	

}
class Singleton{
	public static int value1;
	public static int value2 = 0;
	private static Singleton instance = new Singleton();
	Singleton(){
		value1++;
		value2++;
	}
	public static Singleton getInstance() {
		return instance;
	}
	
}//~out:

Singleton.value1 = 1
Singleton.value2 = 1

 但我們調整一下static域字段的定義順序:

public class MyTest03 {
	public static void main(String[] args) {
		System.out.println("Singleton.value1 = "+Singleton.getInstance().value1);
		System.out.println("Singleton.value2 = "+Singleton.getInstance().value2);
	}
	

}
class Singleton{
	private static Singleton instance = new Singleton();
public static int value1; public static int value2 = 0; Singleton(){ value1++; value2++; } public static Singleton getInstance() { return instance; } }//~out: Singleton.value1 = 1 Singleton.value2 = 0

會發現value2在自增後又被初始化為零了,而value1沒有,static域的對象初始化的順序是依照源文件聲明的順序初始化的,

連接階段準備階段會為靜態域賦初值(int為0)

初始化階段依照聲明順序,先初始化instance引用對象,調用Singleton構造函數 此前value1,value2的值在連接階段被初始化為默認值0.

調用後各自增了1 然後再初始化value1,value2的值,因為value1未被賦初值,故不進行操作,value2的值為1。

==================================可不看=======================================================

public class MyTest03 {

	public static void main(String[] args) {
		Singleton.getInstance();
	}
	

}
class Singleton{
	
	private static Singleton instance = new Singleton();
	public Sub sub1;
	public Sub sub2 = new Sub("sub2");

	public Sub sub3 = new Sub("sub3");
	Singleton(){
		sub1 = new Sub("sub1");
		System.out.println("creating");
	}
	public static Singleton getInstance() {
		return instance;
	}
	
}
class Sub{
	Sub(String str){
		System.out.println(str);
	}
}//~out:sub2
sub3
sub1
creating

 類成員對象的初始化也依照定義順序

==============================================================================================

3.接口的初始化

接口中所有字段均為 public static final

public class MyTest04 {
	MyTest04(String str){
		System.out.println(str);
	}
	public static void main(String[] args) {
		System.out.println(Father04.str);
		System.out.println(Child04.str);

	}

}
interface Father04{
	String str = "Father04";
}
interface Child04 extends Father04{
	String str = "Child04";
}//~out:
Father04
Child04

編譯後就算把接口的字節碼刪除依然不會報錯,static final的字段由於是編譯時常量 被寫入了MyTest04的常量池中。

public class MyTest04 {
	public static void main(String[] args) {
		Child04.sub.toString();

	}

}
interface Father04{
	String str = "Father04";
	Sub sub = new Sub("father");
}
interface Child04 extends Father04{
	String str = "Child04";

	Sub sub = new Sub("child");
}
class Sub{
	Sub(String str){
		System.out.println(str);
	}
}
//~out:child

初始化子接口時,並不會初始化其父接口

類的加載連接初始化順序 (二)