2012-11-23 40 views
17

可能重複:
Why can’t enum’s constructor access static fields?爲什麼枚舉構造函數不能訪問靜態字段

enum Test { 
    e1,e2;  

    int i=0; 
    static int j=5; 

    Test(){ 
    System.out.println(i+" "+j); 
    } 
} 

在上面的代碼構造函數可以訪問實例變量而不是靜態變量J

我已經閱讀了與其他作者有關的答案都說e1和e2在初始化J(靜態字段)之前初始化,但是根據java spec所有靜態字段 初始化的時候曾經把類加載到內存中,也就是在構造函數運行之前。 所以在運行Test()構造函數之前,必須初始化靜態變量j。我無法理解限制,任何機構都可以讓我理解。我已經閱讀了問題的答案Why can't enum's constructor access static fields?但我不滿意如下答案: - 在靜態字段全部被初始化之前調用構造函數。

想,如果採取與一個簡單的類象枚舉另一個例子

class Test{ 
    public static final Test t=new Test(); 
    static int a=5; 

    Test(){ 
    System.out.println(a); 
    } 

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

這裏根據有參數的構造將靜態字段的初始化之前運行,它也運行,因爲它是印刷0(由於JVM做了動初始化)。但沒有編譯錯誤或沒有運行時問題。那麼爲什麼同樣的事情不會發生在枚舉上。

+1

其實很好的問題,我不明白爲什麼這是。可能與Java編譯器如何編譯類文件有關。 – Gerbrand

+1

我不是java專家,但不是枚舉的成員('e1'和'e2'上面)基本上是'enum'的靜態成員?因此,當*他們*被初始化爲值時,必須調用構造函數。但'j'不會被初始化? –

+0

Java中的每個枚舉類似*擴展java.lang.Enum類的類。這個'java.lang.Enum'不能被其他的* normal *類擴展。 所以,你的論點「像枚舉一樣簡單的類」產生預期的輸出是無效的。 – Prasanth

回答

2

問題是,枚舉的實例是在靜態字段初始化期間創建的。他們在你的靜態字段初始化之前創建。 它們必須處於靜態數組值並且可以靜態訪問,所以它是有道理的。正如在anser中爲「爲什麼enum的構造函數不能訪問靜態字段?」所述,它不幸的是,這發生在所有用戶定義的靜態字段初始化之前。 但是如果它被交換了,你不能在靜態初始化中訪問枚舉實例,所以它需要在創建枚舉值之前和之後允許靜態塊。

我不知道是否問題是因爲枚舉值的初始化是Enum類的關注(並且由JVM處理(此邏輯不在Enum類本身中),或者因爲您無法在枚舉值之前放置靜態字段。

爲什麼它是這樣可以回答只有少數人(如喬希布洛赫和Neal Gafter誰被表述爲在Javadoc枚舉的作者,也許有些未知的人)

6

如果你想象有你的枚舉實際上看起來像一類,它是有道理的:

public class Test { 
    // Imagine you cannot move these two statements: 
    public static final Test e1 = new Test(); 
    public static final Test e2 = new Test(); 

    int i=0; 
    static int j=5; 

    private Test(){ 
    System.out.println(i+ " " + j); 
    } 

    static int getJ() { 
    return j; 
    } 


    public static void main(String[] args) { 
    System.out.println(Test.getJ()); 
    } 
} 

此打印:

0 0 
0 0 
5 

如果你可以分享一個具體的例子(而不是理論上的),我們可以建議如何重新設計代碼,以達到預期的效果,儘管靜態字段限制。

相關問題