2012-07-20 119 views
3

我發現它帶有枚舉的凝灰岩。這是Kathy Siera書中的一個例子:枚舉構造函數靜態初始化程序

public class WeatherTest { 

    static Weather w; 

    public static void main(String[] args) { 
     System.out.print(w.RAINY.count + " " + w.Sunny.count + " "); 
    } 
} 

enum Weather { 

    RAINY, Sunny; 
    int count = 0; 

    Weather() { 
     System.out.print("c "); 
     count++; 
    } 
} 

輸出結果是c c 1 1.理解。 現在我想如果計數字段是靜態的呢?輸出是c c 2 2嗎? 基於此,我將count變量修改爲static。 但是我看到的是這樣的: 編譯時間錯誤:非法引用來自初始值設定項的靜態字段。

在網上搜索我發現這是Sun的一種循環漏洞,它允許可以改變靜態字段的靜態方法。好吧..所以現在我用一個靜態方法增加我的工作:

​​

令我驚訝的是,我得到的輸出:c c 0 0! 任何人都可以在拍攝自己之前向我解釋這種行爲嗎?

+0

請解決您的縮進和括號。 – ardent 2012-07-20 16:35:17

+0

非常凝灰岩的問題!所有的Java程序員,自己裝甲:) – Kameron 2012-07-20 16:36:12

+0

ardentsonata:好的 – user1500024 2012-07-20 16:36:50

回答

5

枚舉值可以被認爲是榮耀的靜態字段(它們在下面)。

因此,如果您Weather是一個普通的Java類,它會一直是這樣的:

class Weather { 
    public final static Weather RAINY = new Weather(); 
    public final static Weather Sunny = new Weather(); 

    static int count = 0; 

    Weather() { 
    System.out.print("c "); 
    incr(); 
    } 

    static void incr() 
    { 
     count++; 
    } 
} 

你可以看到,count聲明兩個枚舉值,這意味着它也在兩個值都創建後初始化爲。此外,遇到未初始化的靜態變量的每個函數調用將其視爲使用默認值進行初始化(對於int,它的值爲0)。

因爲你永遠不會調用count已經正確初始化之後incr,你看它的價值仍然0

+0

我同意執行的順序,但是執行這個代碼時我的一部分困惑是在第二次調用時,incr()方法顯示計數爲'2'。根據你的理論,它應該顯示計數爲零,不是嗎? – kosa 2012-07-20 16:49:52

+0

我部分清楚;你能解釋一下在Weather()構造函數中遇到incr()時會發生什麼嗎?爲什麼它不會導致某種編譯器錯誤或異常,因爲我們試圖增加一個尚未初始化的值? – user1500024 2012-07-20 16:51:27

+0

@thinksteep。在第一次調用'incr''' count'時,初始化,所以內存位置的默認值爲'0'。然後它由構造函數遞增2次,然後發生REAL初始化爲'0'。 – 2012-07-20 16:52:28