Java類初始化執行流程

飄渺紅塵✨發表於2021-04-30

    測試程式碼:  

package com.test.ClassLaoderTest;

public  class test1 {
    public static String s_variable = "靜態變數";
    public String init_variable = "公開的變數";
    private String p_variable = "私有的變數";
    //靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("靜態程式碼塊初始化執行了");
    }

    //初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("初始化程式碼塊執行淪");
    }

    //構造方法
    public test1(){
        System.out.println("我是構造方法");
    }

    public static void main(String[] args) {

    }

}

  直接執行:

    

 

 

  main方法裡面不做任何呼叫的情況下,自動呼叫的是靜態程式碼塊和靜態變數

  (2)呼叫靜態變數和靜態方法:

    測試程式碼:    

package com.test.ClassLaoderTest;


public class test1 {
    public static String s_variable = "靜態變數";
    public String init_variable = "公開的變數";
    private String p_variable = "私有的變數";
    //靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("靜態程式碼塊初始化執行了");
    }

    //初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("初始化程式碼塊執行淪");
    }

    //構造方法
    public test1(){
        System.out.println("我是構造方法");
    }

    //靜態方法
    public static void test1(){
        System.out.println("這是靜態方法");
    }
    public static void main(String[] args) {
        System.out.println(test1.s_variable);
        test1.test1();
    }

}

  執行:

  

 

 

  結論:當我呼叫靜態方法/靜態變數時,只會家在靜態程式碼塊,其餘的程式碼塊/構造方法不會被載入

    

  (3)建立物件:

     

package com.test.ClassLaoderTest;


public class test1 {
    public static String s_variable = "靜態變數";
    public String init_variable = "公開的變數";
    private String p_variable = "私有的變數";
    //靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("靜態程式碼塊初始化執行了");
    }

    //初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("初始化程式碼塊執行了");
    }

    //構造方法
    public test1(){
        System.out.println("我是構造方法");
    }

    //靜態方法
    public static void test1(){
        System.out.println("這是靜態方法");
    }
    public static void main(String[] args) {
        test1 t1 = new test1();
    }

}

  執行結果:

    

 

  輸出內容: 

    

靜態變數
靜態程式碼塊初始化執行了
公開的變數
私有的變數
初始化程式碼塊執行了
我是構造方法

  結論:當建立物件/例項化的時候,呼叫順序:靜態程式碼塊->初始化程式碼->構造方法,最後執行的才是構造方法

  

  (4)有繼承關係下的類初始化執行流程:

   環境:

    父類:

     

package com.test.ClassLaoderTest;

public class father {
    public static String s_variable = "父類靜態變數";
    public String init_variable = "父類公開的變數";
    private String p_variable = "父類私有的變數";
    //父類靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("父類靜態程式碼塊初始化執行了");
    }

    //父類初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("父類初始化程式碼塊執行了");
    }

    //構造方法
    public father(){
        System.out.println("我是父類構造方法");
    }

    //父類靜態方法
    public static void test1(){
        System.out.println("這是父類靜態方法");
    }
}

  

    test1.java:

    繼承其父類father:

package com.test.ClassLaoderTest;

public class test1 extends father{
    public static String s_variable = "子類靜態變數";
    public String init_variable = "子類公開的變數";
    private String p_variable = "子類私有的變數";
    //子類靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("子類靜態程式碼塊初始化執行了");
    }

    //子類初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("子類初始化程式碼塊執行了");
    }

    //子類構造方法
    public test1(){
        System.out.println("我是子類構造方法");
    }

    //子類靜態方法
    public static void test1(){
        System.out.println("這是子類靜態方法");
    }

    public static void main(String[] args) {
        
    }
}

  

  main方法不做任何操作,執行:

    

 

 只要extends繼承了,優先呼叫父類靜態程式碼塊

 

(5)有繼承關係下的呼叫靜態方法:

    修改子類即可:

package com.test.ClassLaoderTest;

public class test1 extends father{
    public static String s_variable = "子類靜態變數";
    public String init_variable = "子類公開的變數";
    private String p_variable = "子類私有的變數";
    //子類靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("子類靜態程式碼塊初始化執行了");
    }

    //子類初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("子類初始化程式碼塊執行了");
    }

    //子類構造方法
    public test1(){
        System.out.println("我是子類構造方法");
    }

    //子類靜態方法
    public static void test1(){
        System.out.println("這是子類靜態方法");
    }

    public static void main(String[] args) {
        test1.test1();
        father.test1();
    }
}

 

 

   執行:

      

 

 

 

  結果:

父類靜態變數
父類靜態程式碼塊初始化執行了
子類靜態變數
子類靜態程式碼塊初始化執行了
這是子類靜態方法
這是父類靜態方法

  main方法中,誰優先呼叫靜態方法,就優先載入誰

 

 (6)有繼承關係下的建立物件:

    程式碼:

  

package com.test.ClassLaoderTest;

public class test1 extends father{
    public static String s_variable = "子類靜態變數";
    public String init_variable = "子類公開的變數";
    private String p_variable = "子類私有的變數";
    //子類靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("子類靜態程式碼塊初始化執行了");
    }

    //子類初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("子類初始化程式碼塊執行了");
    }

    //子類構造方法
    public test1(){
        System.out.println("我是子類構造方法");
    }

    //子類靜態方法
    public static void test1(){
        System.out.println("這是子類靜態方法");
    }

    public static void main(String[] args) {
        test1 t1 =new test1();
    }
}

  執行:

   

 

 

   結果:

父類靜態變數
父類靜態程式碼塊初始化執行了
子類靜態變數
子類靜態程式碼塊初始化執行了
父類公開的變數
父類私有的變數
父類初始化程式碼塊執行了
我是父類構造方法
子類公開的變數
子類私有的變數
子類初始化程式碼塊執行了
我是子類構造方法

  結論:通過結果會發現,不管是子類還是父類靜態程式碼塊,靜態程式碼塊在哪裡都是爸爸級別,最先載入的,當建立test1物件的時候,優先載入的是父類程式碼塊,那麼他的初始化執行流程如下:父類靜態程式碼塊>子類靜態程式碼塊>父類初始化程式碼塊>父類構造方法>子類程式碼塊>子類構造方法

   

   

 (7)  有繼承關係下的建立父類物件:

   

package com.test.ClassLaoderTest;

public class test1 extends father{
    public static String s_variable = "子類靜態變數";
    public String init_variable = "子類公開的變數";
    private String p_variable = "子類私有的變數";
    //子類靜態程式碼塊
    static {
        System.out.println(s_variable);
        System.out.println("子類靜態程式碼塊初始化執行了");
    }

    //子類初始化程式碼塊
    {
        System.out.println(init_variable);
        System.out.println(p_variable);
        System.out.println("子類初始化程式碼塊執行了");
    }

    //子類構造方法
    public test1(){
        System.out.println("我是子類構造方法");
    }

    //子類靜態方法
    public static void test1(){
        System.out.println("這是子類靜態方法");
    }

    public static void main(String[] args) {
        father father = new father();
    }
}

 

 執行:

  

 

 

  結果:

    

父類靜態變數
父類靜態程式碼塊初始化執行了
子類靜態變數
子類靜態程式碼塊初始化執行了
父類公開的變數
父類私有的變數
父類初始化程式碼塊執行了
我是父類構造方法

  結論:優先執行的是兩個類的靜態程式碼塊,然後是父型別的程式碼塊和構造方法,而子類的程式碼塊和構造方法沒有被執行是因為沒有例項化子類,所以肯定是沒有他的,那麼只有在建立物件的時候,才會呼叫程式碼塊和構造方法

相關文章