Java靜態代碼塊執行時機


​ 百度一下java的static塊執行時機,搜出來的文章有兩種說法,第一種說static塊是在類的加載時執行(包括我看過的Java視頻都是這么說的),另一種則是反對第一種說法,即static塊並不是在類的加載時執行的,而是在類的初始化時執行的;誰對誰錯,事實用代碼證明。

類的運行步驟

​ 類的運行可分為三個步驟:裝載、連接、初始化

  • 裝載:查找和導入Class文件
  • 連接:把類的二進制數據合並到JRE中,又分為三個步驟
    • 校驗:檢查載入Class文件數據的正確性
    • 准備:給類的靜態變量分配存儲空間
    • 解析:將符號引用轉成直接引用
  • 初始化:對類的靜態變量,靜態代碼塊執行初始化操作(看到這里,結論就已經出來了,但我們還是要用代碼來說話)

用反射機制來證明static塊的執行時機

  • 有一個含static塊的類:
class MyStatic {
    static {
        System.out.println("靜態代碼塊執行了");
    }

    MyStatic() {}
}
  • 先來看一個錯誤的例子(我看的視頻里就是用這個例子來證明static塊是在類的加載時執行的)
public class Test {
    public static void main(String[] args) {
      	Test test = new Test();
        try{
            Class.forName("MyStatic");  //誤認為forName方法運行類只完成加載,實際上forName方法運行時已執行了類的初始化
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

​ 運行結果

靜態代碼塊執行了

​ 靜態代碼塊執行了,然而這並不能代表什么,因為

Class.forName("MyStatic");

​ 等同於

Class.forName("MyStatic", true, test.getClass().getClassLoader());

​ 其中第二個參數指明了是否進行類初始化,將其改成false再試一次

public class Test {
    Test() {}
    public static void main(String[] args) {
        Test test = new Test();
        try{
            Class.forName("MyStatic", false, test.getClass().getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

​ 這時MyStatic類並沒有進行初始化過程,而程序運行沒有任何輸出,得出結論:

Java中靜態代碼塊是在類的初始化過程中執行的,並不是在類的裝載時執行的


免責聲明!

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



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