類的加載連接初始化順序 (二)
阿新 • • 發佈:2019-04-02
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
初始化子接口時,並不會初始化其父接口
類的加載連接初始化順序 (二)