java中new一個對象的執行過程及類的加載順序


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


免責聲明!

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



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