2016-06-30 106 views
0

當試圖創建一個標誌枚舉讓它包含多個狀態時。我注意到一些奇怪的東西。更改枚舉的內部值時,它的名稱不會更改。奇怪的是,這種內在價值(在我的情況下,一個int)保持的最高值,直到我明確的值設置爲0爲什麼在枚舉設置爲null後,此值得到保留

這是我用過進一步測試該

public enum flags { 
    None(0), flag1(1 << 0); 

    private int value; 

    private flags(int value) { 
     this.value = value; 
    } 

    public boolean hasFlag(flags flag) { 
     return (flag.value & value) == flag.value; 
    } 

    public void addFlag(flags flag) { 
     value |= flag.value; 
    } 

    public int getValue() { 
     return value; 
    } 

    public void setValue(int value) { 
     this.value = value; 
    } 
} 
枚舉

我嘗試了這些東西來設置枚舉值0

flags flag = flags.None; 
    System.out.println(flag + " " + flag.getValue()); 
    // prints: None 0 

    flag.addFlag(flags.flag1); 
    System.out.println(flag + " " + flag.getValue()); 
    // prints: None 1 

    flag = flags.None; 
    System.out.println(flag + " " + flag.getValue()); 
    // prints: None 1 even though 
    // its been set to flags.None which has a value of 0 

    flag = null; 
    flag = flags.None; 
    System.out.println(flag + " " + flag.getValue()); 
    // prints: None 1. Even though the enum has been set to null before 
    // setting the value to null 

    flag = null; 
    flag = flags.flag1; 
    flag = flags.None; 
    System.out.println(flag + " " + flag.getValue()); 
    // prints: None 1. Even though it is set to 
    // another value after being set to null 
    // and then set to None 

    flag.setValue(0); 
    System.out.println(flag + " " + flag.getValue()); 
    // prints: None 0. As expected 

我的問題是:爲什麼 如此執着的價值,這裏發生了什麼?

+2

您正在修改兩個對象的狀態。你爲什麼驚訝自己的狀態被修改了? –

+0

enum上的setter應該是一個紅旗(雙關語意思)。 – Robert

+0

作爲一個說明,最好遵循約定,並使用駱駝案例爲你的枚舉/類名等 – Orestis

回答

1

問題是,枚舉每個值只有一個實例(在您的情況下爲Noneflag1)。因此編輯這一個實例將會永遠改變它。如果您將標記添加到None,則原始None實例將發生更改(與flags.None中的更改相同),並且將保持這種狀態,直到您再次更改爲止。

5

我認爲你嚴重誤解了Java的枚舉的目的和功能。枚舉根據定義singletons,這意味着枚舉的每個定義每個運行時只能構造一次。換句話說,你不能有兩個flags.None實例;當你的應用程序運行時,flags.None是一件永恆的事情。

可以 --however - 聲明多個字段,參考您的枚舉。就像您可能會說int i = 0一樣,您可以聲明一個「flags」變量,如flags myFlag = flags.None。這不會創建新版本的「無」,但它是對「無」枚舉的引用。在整個應用程序中,修改「無」(這是一個糟糕的主意恕我直言)的狀態將在全球範圍內看到。

此外,您不應該將自己的位置轉換爲您編寫的枚舉。我可以建議你看看EnumSet?這將產生更多可讀的代碼,並且是實現它看起來像你試圖完成的有利方式。

1

當您聲明一個枚舉時,您正在有效地聲明一系列靜態對象。通過改變靜態對象的成員(addFlag調用),你已經修改了它,所有更多的引用將引用相同的值。

你誤解的另一部分是,當你將標誌分配給null或其他值時,你並沒有清除枚舉。 Java是通過引用傳遞的,所以你所做的就是改變標誌變量所指的內容。這就是爲什麼在代碼結束時,當您將值設置爲0時,枚舉的None成員再次按預期顯示0。您可以通過重新分配None和flag1枚舉成員的值來解決此問題。

最後,這實際上不是如何使用枚舉。我不確定你試圖使用這個功能,但是你可以根據你在這裏提供的內容輕鬆地使用普通班。如果要進行嚴格的類型檢查並清楚地指示(命名)每個值的含義,那麼最好使用枚舉。例如一個錯誤代碼枚舉。但是內部的值不應該被重新分配或修改。當然,顯然你可以做到這一點,我只是說它可能會混淆看到你的工作的其他人。

+0

這真的是我在一個項目中偶然發現的事情,我不必擔心了。 –

相關問題