1,new一個對象時代碼的執行順序
(1)加載父類(以下序號相同,表明初始化是按代碼從上到下的順序來的)
1.為父類的靜態屬性分配空間並賦於初值
1.執行父類靜態初始化塊;
(2)加載子類
2.為子類的靜態屬性分配空間並賦於初值
2.執行子類的靜態的內容;
(3)加載父類構造器
3.初始化父類的非靜態屬性並賦於初值
3.執行父類的非靜態代碼塊;
4.執行父類的構造方法;
(4)加載子類構造器
5.初始化子類的非靜態屬性並賦於初值
5.執行子類的非靜態代碼塊;
6.執行子類的構造方法.
總之一句話,靜態代碼塊內容先執行(父先后子),接着執行父類非靜態代碼塊和構造方法,然后執行子類非靜態代碼塊和構造方法。
當然細分加載過程的話,看下面JVM加載過程,靜態代碼塊是在類加載時執行,非靜態代碼塊和加載器在實例初始化時執行。
注意兩個問題:
1)靜態變量和靜態代碼塊的初始化順序:誰在前面先初始化誰(這個也比較容易理解,初始化的時候,不可能跳着去初始化吧,比如說靜態代碼塊在靜態變量的前面,不可能先跳過靜態代碼塊的初始化先去執行靜態變量的初始化吧。)
2)子類的構造方法,不管這個構造方法帶不帶參數,默認的它都會先去尋找父類的不帶參數的構造方法。如果父類沒有不帶參數的構造方法,那么子類必須用supper關鍵子來調用父類帶參數的構造方法,否則編譯不能通過。
2,Java中類被JVM加載(加載、鏈接、初始化)
有三種: 靜態初始化塊、實例初始化塊、構造器。
靜態初始化塊,在類被JVM的類加載器加載時就被執行了;
而實例初始化塊和構造器是在類實例化對象(例如new)時才被執行的。
執行順序:
父類靜態初始化塊 > 子類靜態初始化塊 > 父類實例初始化塊 > 父類構造器 > 子類實例初始化塊 > 子類構造器
例1:main()方法中為空(即無調用只加載)
public class Singleton { //靜態變量 public static int num; //靜態初始化塊 static{ System.out.println(num+":靜態初始化塊"); } //實例初始化塊 { System.out.println(num+":實例初始化塊"); } //構造方法 public Singleton(){ System.out.println(num+":構造函數初始化"); num++; } //靜態方法 public static void getInstance(){ System.out.println(num+":靜態方法初始化"); } public static void main(String[] args) { } }
結果為:0:靜態初始化塊
上述結果說明:
在加載時,靜態變量就進行了初始化並賦了默認值;靜態初始化塊也執行了;其他並沒有執行。
例2:main()方法實例化兩次
public class Singleton { //靜態變量 public static int num = 0; //靜態初始化塊 static{ System.out.println(num+":靜態塊初始化"); } //構造方法 public Singleton(){ System.out.println(num+":構造函數初始化"); num++; } //實例初始化塊 { System.out.println(num+":實例塊初始化"); } //靜態方法 public static void getInstance(){ System.out.println(num+":靜態方法初始化"); } public static void main(String[] args) { new Singleton(); new Singleton(); } }
結果為:
0:靜態初始化塊
0:實例初始化塊
0:構造函數初始化
1:實例塊初始化
1:構造函數初始化
說明:
(1)靜態初始化塊只是在類加載時執行一次,對類實例化時並不會再執行;
(2)類中靜態方法並沒有執行,因此只有在調用時才會執行;
(3)這三種類的初始化塊的執行順序:靜態初始化塊(加載時)---實例初始化塊(實例化時)---構造函數初始化(實例化時)
例3:
public class Singleton { //靜態變量 public static int num = 0; static Singleton ai = new Singleton(); //靜態初始化塊 static{ System.out.println(num+":靜態塊初始化"); } //構造方法 public Singleton(){ System.out.println(num+":構造函數初始化"); num++; } //實例初始化塊 { System.out.println(num+":實例塊初始化"); } //靜態方法 public static void getInstance(){ System.out.println(num+":靜態方法初始化"); } public static void main(String[] args) { } }
結果:
0:實例塊初始化
0:構造函數初始化
1:靜態塊初始化
說明:
(1)加載時,靜態成員是依次運行的,這里先是靜態變量,然后是靜態引用,然后是靜態塊;
(2)當把創建引用即new對象的語句前的static關鍵字去掉后,該語句就不執行了,所以說明加載時是識別的static而不是new。
http://www.cnblogs.com/ivanfu/archive/2012/02/12/2347817.html
https://blog.csdn.net/u012276993/article/details/22393963