關於類加載的時候,static代碼塊中可以賦值但不能引用的問題


關於類加載的時候,static代碼塊中可以賦值但不能引用的問題

類加載過程

image-20200925104632965

先看代碼:

class StaticTest{
    static {
        a=10;
        System.out.println(a);//報錯:Illegal forward reference
    }
    static int a=1;

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

編譯不通過,報錯信息說非法的前向引用,因為對於a的聲明在下面的靜態變量中,屬於語法錯誤,jvm編譯不通過。

如果去掉輸出這句,變成下面的代碼:

class StaticTest{
    static {
        a=10;
    }
    static int a=1;

    public static void main(String[] args) {
        StaticTest staticTest = new StaticTest();
        System.out.println(a);
    }
}

輸出結果為:1

問題:為什么a還沒有被聲明就可以被賦值,為什么不報錯?

答:

1.類加載的時候在連接階段的准備中,做了下面的事情:

為類的靜態變量分配內存並設置默認初始值,這些變量所使用的內存都將在方法區中進行分配。

注意:

這時候進行內存分配的僅包括類變量(static),而不包括實例變量,實例變量會在對象實例化的時候隨對象一起分配到堆中。
這些內存都將在方法區中分配
非常量(final)的靜態數據類型被默認賦對應類型的零值(如0、0L、null、false等),而不是程序中顯示的賦值。

准備階段檢測到了aint,分配內存並為a賦初值0

2.然后進入初始化階段之后,對靜態代碼塊執行初始化,靜態變量顯示初始化。

初始化的順序為代碼排列順序。如靜態代碼塊在靜態變量聲明前,靜態變量a在靜態代碼塊和靜態變量中分別做了賦值,則a先被靜態代碼塊賦值,后被靜態變量賦值語句賦值。並且靜態語句塊只能訪問到定義在靜態語句塊之前的變量,定義在它之后的變量,在前面的靜態語句塊可以賦值,但是不能訪問

所以說初始化之前a=0,先執行static代碼塊,a=10;然后執行靜態變量,a=1;


免責聲明!

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



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