2010-01-13 39 views
7

Java是否允許類似於良好的C或甚至C#的東西,因爲您可以使用自動增加值的字段來定義枚舉,並從可選的值開始?Java枚舉自動增加條目?

E.g.

在C或C#:

enum Foo { A = 10, B, C, D = 5000, E, Fish }; 

息率A = 10,B = 11,C = 12,d = 5000,E = 5001,炸魚= 5002

回答

10

在Java你不能t在處明確指定序數值。它們總是從0開始自動遞增,但無法控制它。

如果您需要其他自定義值,則需要將它們放在構造函數調用中並自行存儲。您可以得到自動增量,但它的噁心赫克:

import java.util.EnumSet; 

// Please don't ever use this code. It's here so you can point and laugh. 
enum Foo 
{ 
    A(10), B, C, D(5000), E, Fish; 

    private static int nextValue; 
    private int value; 

    private Foo() 
    { 
     this(Counter.nextValue); 
    } 

    private Foo(int value) 
    { 
     this.value = value; 
     Counter.nextValue = value + 1; 
    } 

    public int getValue() 
    { 
     return value; 
    } 

    private static class Counter 
    { 
     private static int nextValue = 0; 
    } 
} 

public class Test 
{ 
    public static void main(String[] args) 
    { 
     for (Foo foo : EnumSet.allOf(Foo.class)) 
     { 
      System.out.println(foo.name() + " " + 
           foo.ordinal() + " " + 
           foo.getValue()); 
     } 
    } 
} 

注意需要嵌套類,因爲你不能枚舉構造器中訪問靜態字段。 Ick,ick,ick。請不要這樣做。

+0

'這是你在這兒可以指向和laugh.'哈哈。好的! – 2010-01-13 09:00:03

+0

默認的構造函數需要更新Counter.nextValue,你也可以在Foo中直接刪除nextValue。 – Yuliy 2010-01-13 09:06:53

+0

@Yuliy:無參數構造函數調用參數化構造函數,因此更新Counter.nextValue。將nextValue直接放在Foo *內部不會工作 - 至少不會與我正在使用的javac版本無關。它阻止你訪問構造函數中的靜態字段。 – 2010-01-13 09:27:28

10

這是Java Enums的設計選擇,不支持更改序號值。基本上,他們是不夠穩定足以依賴他們。如果您在示例客戶端中更改B和C的位置,則取決於序號值是否被破壞。這可能會無意中發生。

該問題在Effective Java Item 31: Use instance field instead of ordinals中描述。

可以穩定地模仿行爲:

enum X{ 
    A(10), B(A), C(B), D(5000), E(D), F(E); 

    private final int value; 

    X(int value){ 
     this.value = value; 
    } 

    X(X preceding){ 
     this.value = preceding.getValue() + 1; 
    } 

    public int getValue() { 
     return value; 
    } 

    @Override 
    public String toString() { 
     return this.name() + "(" + this.value + ")"; 
    } 

    static { 
     Set<Integer> values = new HashSet<Integer>(); 
     for(X x : X.values()) values.add(x.value); 
     assert(values.size() == X.values().length); //no duplicates 
    } 
} 

根據這個定義,你可以改變值的順序而不斷裂的客戶。

調用for(X x : X.values()) System.out.println(x);回報:

A(10) 
B(11) 
C(12) 
D(5000) 
E(5001) 
F(5002) 
+0

有點糟糕 - 他們有他們的用途。例如,當我不希望我的枚舉的值低於N時(例如,我可能想要保留該範圍以禁止)。但我也不想自己手動定義每個整數值... – 2010-01-13 08:57:56

+0

@alex:這意味着您應該有一個字段,它根據您想要的範圍的約束條件計算序數中的數字。 – Chii 2010-01-13 09:01:38

+0

@Alex - 仿真版本應該適合您。它很穩定,你不需要明確地輸入每個int值。 – 2010-01-13 09:20:42