2010-01-13 11 views
7

Czy Java zezwala na coś w rodzaju dobrego ol C, czy nawet C# w tym sensie, że można zdefiniować wyliczenie z polami, które automatycznie rosną w wartości i zaczynają od opcjonalnie podanej wartości?Wejścia do automatycznego zwiększania Java?

E.g.

w C lub C#:

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

plony A = 10, B = 11, C = 12, D = 5000 E = 5001, Ryba = 5002.

Odpowiedz

10

W Javie można” t podać wartości porządkowe jawnie w ogóle. Oni zawsze autoinkrementacji, od 0, bez kontroli nad nim.

Jeśli chcesz uzyskać inne wartości niestandardowe, musisz umieścić je w wywołaniach konstruktora i przechowywać je samodzielnie. Ci może dostać AUTOINCREMENT, ale icky jak cholery:

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()); 
     } 
    } 
} 

Uwaga potrzeba zagnieżdżonej klasy, ponieważ nie można uzyskać dostęp do pól statycznych wewnątrz konstruktora enum. Ick, ick, ick. Proszę tego nie robić.

+0

'Jest tu więc można wskazać i laugh.' Haha. Dobry! –

+0

domyślny konstruktor musi zaktualizować Counter.nextValue i prawdopodobnie możesz usunąć nextValue bezpośrednio w Foo. – Yuliy

+0

@Yuliy: Konstruktor bez parametrów wywołuje sparametryzowaną, więc aktualizuje Counter.nextValue. Umieszczenie nextValue bezpośrednio w Foo * nie * działa - przynajmniej nie w wersji javac, której używam. Zapobiega uzyskiwaniu dostępu do pól statycznych w konstruktorze. –

10

Jest to wybór projektu Java Enums, aby nie obsługiwać zmiany wartości porządkowych. Zasadniczo są one niezbyt stabilne wystarczy na nich polegać. Jeśli zmienisz pozycję B i C w przykładowych klientach, w zależności od wartości porządkowych są zepsute. Może się to zdarzyć nieumyślnie.

Problem opisano w Efektywna Java Item 31: Use instance field instead of ordinals.

można naśladować zachowanie w sposób stabilny:

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 
    } 
} 

Z tej definicji można zmienić kolejność wartości bez zerwania klientów.

Wywoływanie for(X x : X.values()) System.out.println(x); powraca:

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

Kinda jest do bani - mają swoje zastosowania. Na przykład wtedy, gdy nie chcę, aby moje wyliczenia miały wartości poniżej N (może chcę zarezerwować ten zakres jako niedostępny). Ale ja też nie chcę ręcznie definiować wartości liczby całkowitej samodzielnie ... –

+0

@alex: oznacza to, że powinieneś mieć pole, które oblicza liczbę z liczby porządkowej, biorąc pod uwagę ograniczenia zakresu, który chcesz. – Chii

+0

@Alex - Emulowana wersja powinna działać dla ciebie. Jest stabilny i nie musisz bezpośrednio wstawiać wartości int. –

Powiązane problemy