成員變量賦值問題【向前引用】

今天,同窗問了我一個問題,代碼以下html

public class Test10 {

    //這個小程序 爲啥不報錯,應該是先執行a=10這個程序塊,可是咱們沒有設定a的類型啊
    {
        a = 10;
    }

    int a = 20;


    public static void main(String[] args) {
        Test10 t = new Test10();
        System.out.println("a的數值爲:" + t.a);
    }
}
  • 開始的時候,我看到這個代碼有點懵了(臥槽,誰會這樣用啊),因而我就在想:爲何不報錯,是否是JVM會把代碼全都編譯一次,執行到構造代碼塊的時候,發現後面有對a變量進行定義,因此沒有報錯。因而就上網查資料去了,後來發現java支持向前引用
  • 接着,我發現輸出的值是20(臥槽,怎麼是20???,不該該是a=10構造代碼塊覆蓋了在定義成員變量時a=20嗎)
  • 因而乎,我又做死地加入了一個構造函數進去,看看執行順序究竟是怎麼樣的
public class Test10 {


    public Test10() {

        a=30;
    }

    //這個小程序 爲啥不報錯,應該是先執行a=10這個程序塊,可是咱們沒有設定a的類型啊
    {
        a = 10;
    }

    int a = 20;


    public static void main(String[] args) {
        Test10 t = new Test10();
        System.out.println("a的數值爲:" + t.a);
    }
}
  • 由於java支持向前引用,構造函數的a那固然不會報錯啦。我再次執行該測試的時候,發現a的值爲30,此時又懵逼了。按我當時理解是這樣的(既然上面輸出的是20,那麼我加入構造方法,構造方法在構造代碼塊後執行,一樣會被a=20覆蓋掉【當時候腦殼短路了,忘記構造方法會覆蓋掉成員變量的值】
  • 最後我在知乎RednaxelaFX—-R大中一個回答中彷佛找到了答案。截圖以下:

  • 簡要提煉下語句:對JVM來講全部實例初始化動做都要收集到「特殊的實例初始化方法」(名爲「init」,內容對應全部實例初始化器+構造器)裏,按代碼順序把實例初始化動做(包括實例字段初始化與匿名的實例初始化器)收集起來,而後是構造器自身的內容
  • 就是說構造代碼塊和成員變量的賦值順序是依照代碼的順序執行的
  • 剔除構造方法,將構造代碼塊和聲明成員變量位置交換一下,看看結果
public class Test10 {


    int a = 20;

    {
        a = 10;
    }


    public static void main(String[] args) {
        Test10 t = new Test10();
        System.out.println("a的數值爲:" + t.a);
    }
}
  • 輸出的結果是10。java

  • ps:若是我有理解錯誤的地方,請留言,謝謝!小程序

參考資料:markdown

向前引用:http://www.cnblogs.com/nokiaguy/p/3156357.html函數

執行順序RednaxelaFX的回答:https://www.zhihu.com/question/36643366?q=java%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E5%88%B0%E5%BA%95%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E8%A2%AB%E8%B5%8B%E5%80%BC%EF%BC%9F測試

相關文章
相關標籤/搜索