關於Java的靜態塊、非靜態塊和靜態方法

一、代碼塊和構造函數的初始化順序
先從實例代碼開始
父類

public class SuperClass {

    static {
        System.out.println("super static block init");
    }

    {
        System.out.println("no static block init");
    }

    public SuperClass() {
        System.out.println("super Instance");
    }

子類

 public class SubClass extends SuperClass {
    static {
        System.out.println("sub static block init");
    }

    {
        System.out.println("sub no static block init");
    }

    public SubClass() {
        System.out.println("sub Instance");
    }
}

下面這行代碼的數據結果是什麼?

SuperClass superClass = new SuperClass();

輸出結果

super static block init
no static block init
super Instance

總結:針對單個類,初始化順序:靜態代碼塊,非靜態代碼塊,構造函數


下面的這行代碼又會輸出怎麼樣的結果?

SubClass subClass = new SubClass();

輸出結果

super static block init
sub static block init
no static block init
super Instance
sub no static block init
sub Instance

子類實例化時,輸出的順序如下:
父類的靜態代碼塊->子類的靜態代碼塊->父類的非靜態代碼塊->父類的構造函數->子類的非靜態代碼塊->子類的構造函數


二、代用靜態方法和靜態變量
下面的示例代碼分析

父類

public class SuperClass {
    static {
        System.out.println("super static block init");
    }

    {
        System.out.println("no static block init");
    }

    public SuperClass() {
        System.out.println("super Instance");
    }

    public static void superTest() {
        System.out.println("super method");
    }

    public static final Integer countInteger = 123;

    public static final int countInt = 345;
}

子類

public class SubClass extends SuperClass {
    static {
        System.out.println("sub static block init");
    }

    {
        System.out.println("sub no static block init");
    }

    public SubClass() {
        System.out.println("sub Instance");
    }

    public static void sub() {
        System.out.println("sub method");
    }

    public static final String hello = "hello";
    public static final int testInt = 3;
    public static final Integer testInteger = 4;
}

觀察輸出結果:

System.out.println(SuperClass.countInt); 
//345
********************
System.out.println(SuperClass.countInteger);
// super static block init
// 123
********************
System.out.println(SubClass.countInteger);
// super static block init
// 123
********************
System.out.println(SubClass.countInt);
// 345
********************
SuperClass.superTest();
// super static block init
// super method
********************
SubClass.superTest();
// super static block init
// super method
********************
System.out.println(SubClass.testInt);
// 3
********************
System.out.println(SubClass.testInteger);
// super static block init
// sub static block init
// 4
********************
System.out.println(SubClass.hello);
// hello
********************
SubClass.sub();
// super static block init
// sub static block init
// sub method
********************
SubClass[] subClasses = new SubClass[2];//無任何內容輸出

總結

  1. 子類調用父類的靜態字段或者靜態方法,只會觸發父類的初始化;
  2. 父類調用父類的靜態方法,會觸發父類的靜態塊初始化;
  3. 子類調用子類的靜態方法,會觸發父類的靜態塊和子類的靜態塊的初始化;
  4. 關於Int,string 和Integer輸出結果的不同,是由於Int和string類型在編譯階段jvm放到了常量池中。

參考:https://segmentfault.com/a/1190000005916150

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章