2010-07-29 14 views
6

Czy można zdefiniować coś takiego w java?Liczba dla każdego artykułu wyliczeniowego?

C# Kod:

public enum Character 
{ 
    A = 1, 

    B = 2, 

    C = 4, 

    D = 8 

} 


... 

Character ch = /* from user */ 

if(ch & Character.A) 
{ 
    // some operation... 
} 

na przykład jeśli ch zestaw do Character.B następnie prowadzić z if będzie false:

ch = 00000000 00000000 00000000 00000010 
A = 00000000 00000000 00000000 00000001 
------------------------------------------ 
& 00000000 00000000 00000000 00000000 

Chcę zaimplementować coś takiego! Czy jest to kiedykolwiek możliwe w Javie?

Odpowiedz

17

Cóż, można prawie zrobić:

public enum CharEnum // Let's avoid java.lang.* clashes 
{ 
    A(1), B(2), C(4), D(8); 

    private final int mask; 

    private CharEnum(int mask) 
    { 
     this.mask = mask; 
    } 

    public int getMask() 
    { 
     return mask; 
    } 
} 

Następnie:

CharEnum ch = /* from user */ 

if ((ch.getMask() & CharEnum.A.getMask()) > 0) 
{ 
    // some operation... 
} 

ta może być przydatna w niektórych sytuacjach, ale jak powiedział Michael powinno się patrzeć na EnumSet do ogólnego "zestaw wartości" opcji.

Jeśli zrobić decydują się na wyliczenia z wartościami, które można umieścić dodatkową logikę wewnątrz samego wyliczenia:

public enum CharEnum 
{ 
    // Other code as before 

    public boolean overlapsWith(CharEnum ch) 
    { 
     return (ch.mask & mask) > 0; 
    } 
} 
+0

Powinieneś dodać kilka nawiasów: 'if ((ch.getMask() i CharEnum.A.getMask())> 0)' –

+0

@ True: Fixed, thanks. –

4

(Oczywiście, wybierając Character jako nazwę swojej enum jest bardzo mylące, gdyż tworzy konflikt z java.lang.Character który jest automatycznie importowane do każdej jednostki kompilacji)

Można użyć metody porządkowej(), aby uzyskać liczba całkowita związana ze stałą wyliczenia. W każdym razie mam wrażenie, że to, co próbujesz osiągnąć, może zostać zrealizowane za pomocą metod zdefiniowanych przez enum. Mam na myśli, wyrocznia Javy są potężniejsze niż C/C++, ponieważ można skojarzyć zachowanie z nimi.

public enum Chr { 
    A { 
     @Override public void doSomething(int c) { 
     // some operation ... 
     } 
    }, 
    B, 
    C, 
    D; 

    public void doSomething(int c) { 
     // some default behavior 
    } 
    } 

obserwuję swój komentarz:

Można zdefiniować pole, które będzie utrzymać tę wartość, i konstruktor zainicjować w następujący sposób:

public enum Chr { 
    A(1), 
    B(2), 
    C(4), 
    D(8) 
    ; 

    public Chr(int n) { value = n; }   
    public final int value; 
    } 



    Character ch = ... // from user 
    if(ch & Chr.A.value) { 
    ... 
    } 
2

Można zrobić coś takiego za pomocą Enum.ordinal(), ale byłby to naprawdę zły projekt. Powinieneś użyć == do porównań równości i EnumSet dla operacji zestawu.

1

zgadzam się z Itay i dostać nieco dalej będę polecam lektura Effective Java Second Edition o pełny rozdział naprawdę interesujące na wyliczeniach Java.

1

Zgadzam się z Michaelem Borgwardtem i Jonem Skeetem, że warto przyjrzeć się EnumSet. Wybrałbym EnumSet w bitowych operacjach, jak to masz, więc pokażę, jak używać EnumSet.

 

To wygląda jak Character wyliczenia (nazwijmy go CharEnum od teraz) CharEnum jest używany jak pole bitowe, gdzie każdy enum ma wartość int z tylko jednym bitem:

A = 00000000 00000000 00000000 00000001 
B = 00000000 00000000 00000000 00000010 
C = 00000000 00000000 00000000 00000100 
D = 00000000 00000000 00000000 00001000 

Jest to bardzo podobne do tego, co robi dla ciebie EnumSet; ma wewnętrzny wektor bitowy, który automatycznie przypisuje każde wyliczenie do bitu na long. Jak mówi JavaDoc, "Wydajność w czasie i przestrzeni tej klasy powinna być wystarczająco dobra, aby umożliwić jej użycie jako wysokiej jakości, bezpiecznej dla zdrowia alternatywy dla tradycyjnych" bitowych flag "opartych na int."

Oto przykładem tego, jak go używać

public enum CharEnum { 
    A, B, C, D; 
} 

a następnie

EnumSet<CharEnum> ch = /* from user */ 

if (ch.contains(CharEnum.A)) { 
    // some operation... 
} 

nie ma potrzeby, aby określić bity wszędzie, więc jest to znacznie prostsze kod!

Ostrzeżenie: działa to tylko dlatego, że wartości wyliczeniowe w przykładzie C# mają tylko jeden bit ustawiony. Jeśli miał wartość enum tak:

E = 00011000 01110111 11100101 10000101 

wtedy EnumSet nie byłoby właściwe. W takim przypadku powinieneś spojrzeć na jedną z pozostałych odpowiedzi tutaj.

Powiązane problemy