Jak przekonwertować wartość enum na int?

240

Mam funkcję, która zwraca typ int. Mam jednak tylko wartość wyliczenia podatku.

Jak mogę rzutować wartość wyliczenia podatku na int?

public enum TAX {
    NOTAX(0),SALESTAX(10),IMPORTEDTAX(5);

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

TAX var = TAX.NOTAX; // This value will differ

public int getTaxValue()
{
  // what do do here?
  // return (int)var;
}
vrbilgi
źródło
1
Możliwy duplikat How to match int int enum
malat

Odpowiedzi:

354

Trzeba by valuejakoś ujawnić wyliczenie , np

public enum Tax {
    NONE(0), SALES(10), IMPORT(5);

    private final int value;
    private Tax(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

...

public int getTaxValue() {
    Tax tax = Tax.NONE; // Or whatever
    return tax.getValue();
}

(Zmieniłem nazwy, aby były nieco bardziej konwencjonalne i czytelne, przy okazji).

Jest to zakładając chcesz wartość przypisaną w konstruktorze. Jeśli nie tego chcesz, musisz podać nam więcej informacji.

Jon Skeet
źródło
1
@likejiujitsu: To idzie w przeciwnym kierunku. W tym pytaniu OP ma już wartość typu Taxi chce z niej uzyskać wartość liczbową.
Jon Skeet,
Właśnie go wypróbowałem i zdałem sobie sprawę, że zawodzi, myEnumValue = MyEnum.valueOf(myInt);że arg musi być typu String - czy jest coś, czego mi brakuje?
likejudo
To rozwiązanie jest gorsze niż nic. Wydaje się, że wyliczenia w Javie po prostu nie powinny być używane? A może JDK 1.8 to zmieniło?
ebyrob,
@ebyrob: Biorąc pod uwagę głosowanie, wydaje się, że wiele osób nie zgadza się z tobą, tak jak ja. Jeśli chcesz mieć stały zestaw wartości, wyliczenia są absolutnie w porządku.
Jon Skeet,
209

Wolę to:

public enum Color {

   White,

   Green,

   Blue,

   Purple,

   Orange,

   Red
}

następnie:

//cast enum to int
int color = Color.Blue.ordinal();
Vivia
źródło
34
Jest to niepoprawne / niezalecane przez Joshua Blocha w jego książce Effective Java (2nd ed). Patrz pozycja 31.
504342
43
@ user504342 Nie mam drugiego wydania książki, więc czy możesz podać sedno, dlaczego nie jest to zalecane?
likejudo
17
2 powody: po pierwsze, każde powiązanie między wartościami porządkowymi a stałymi zostanie zerwane, jeśli zostaną dodane nowe stałe, a dwa dokumenty API szczególnie tego zalecają.
jordanpg
8
Tak czysty i idealny. Widzę kilka „nie rób tego” i „nie polecam”. Będę musiał zbadać, dlaczego uważa się to za złe. Niektóre wzdęte próbki źle wyglądają w IMO. Tyle pracy do wykonania tak prostego zadania.
Herb Meehan,
4
W zespole jesteś pewien, że Twój współtwórca doda wartość pośrodku (gorzej na początku), lub po prostu posortuje je, ponieważ nie mają nic do roboty i całkowicie zepsują kod przy użyciu.ordinal()
Michael Laffargue
18

Jeśli chcesz przypisać wartość do konstruktora, musisz dodać metodę do definicji wyliczenia, aby zwrócić tę wartość.

Jeśli chcesz unikalny numer reprezentujący wartość wyliczenia, możesz użyć ordinal().

unholysampler
źródło
2
Bądź ostrożny. Istnieje wiele innych rozwojowych anty-wzorów, które opierają się na ordinal()ważnych przypadkach użycia ordinal(). Jeśli chcesz zapisać unikalną wartość enum, po prostu zapisz enum. Istnieją EnumSets, Listy Enums, EnumMaps i prawie każda inna kolekcja Enum, która może być dostępna.
Edwin Buck
1
@EdwinBuck: Warto to zaznaczyć, chciałem tylko wspomnieć o istnieniu, ordinal()ponieważ OP nie wyjaśniło, czym naprawdę jest int.
unholysampler
Nie bierz porządków. Sprawdź enum api w tym zakresie. Usunięto głosowanie up.
Hovercraft Full Of Eels
3
Zastanawiam się, jakie są myśli ludzi na temat wykorzystania ordinal()wewnętrznego w samym wyliczeniu. Na przykład, że mam enum nazwie „ Season”, który zawiera wartości Spring, Summer, Autumn, i Winter, i to metoda publiczna o nazwie next(), która zwraca values()[(ordinal() + 1) % 4] Zewnętrznie, brak kodu kiedykolwiek widzi numer porządkowy, i nigdy nie będzie dodatkowych członków w tym wyliczenia, więc wygląda na to, że jest to poprawny przypadek użycia.
Darrel Hoffman
1
@DarrelHoffman Mam wrażenie, że robienie tego jest w porządku, ponieważ jedyne mocne argumenty, które widzę, przeciwko używaniu ordinal()zawiasu na odległym kodzie są łamane przez zmiany stałych wyliczania wyliczenia. Jeśli zamierzasz zmodyfikować stałe wyliczenia, musisz już znajdować się w tym pliku. Większość wyliczeń jest dość krótka, a jeśli nie, powinieneś dokładnie sprawdzić plik. W obu przypadkach prawdopodobnie powinieneś mieć test jednostkowy obejmujący twoją next()metodę.
Alan Hensley
12

Czasami pewne podejście w C # ułatwia życie w świecie Java ..:

class XLINK {
static final short PAYLOAD = 102, ACK = 103, PAYLOAD_AND_ACK = 104;
}
//Now is trivial to use it like a C# enum:
int rcv = XLINK.ACK;
Vladi
źródło
Dla mnie jest to najbardziej pożądana droga. Dostaję korzyści z enum (klarowność kodu), typu danych przyjaznego dla DB i nie muszę badać 100 alternatyw enum, aby zrobić to w „androidowy sposób”. Prosty i skuteczny.
John Ward
Miły. To tak, jakby wyliczenie java jest po prostu całkowicie odłączone od rzeczywistości tego, do czego używa się wyliczenia ... zwłaszcza jeśli ludzie zaczną nadużywać go do takich rzeczy jak singletony. Takie podejście ma tę wadę, że nie ma łatwego sposobu na uzyskanie wszystkich wartości.
Nyerguds,
Czy nie ma to wady próby przekazania wartości wyliczeniowej do metody? Nie można już przekazać XLINK do metody, ponieważ nie reprezentuje ona niczego konkretnego. Tracisz pisanie w swojej metodzie. Podpis metody musiałby być czytany krótko zamiast XLINK.
Dustin Jensen,
2

Być może lepiej jest użyć reprezentacji ciągu niż liczby całkowitej, ponieważ ciąg jest nadal ważny, jeśli wartości są dodawane do wyliczenia. Możesz użyć metody enum name () do przekonwertowania wartości enum na String i metody enum valueOf () w celu ponownego utworzenia reprezentacji enum z String. Poniższy przykład pokazuje, jak przekonwertować wartość wyliczenia na String i wstecz (ValueType jest wyliczeniem):

ValueType expected = ValueType.FLOAT;
String value = expected.name();

System.out.println("Name value: " + value);

ValueType actual = ValueType.valueOf(value);

if(expected.equals(actual)) System.out.println("Values are equal");
Mikrofon
źródło
1
public enum Tax {

NONE(1), SALES(2), IMPORT(3);

private final int value;
    private Tax(int value) {
        this.value = value;
    }

    public String toString() {
        return Integer.toString(value);
    }
}

class Test {
    System.out.println(Tax.NONE);    //Just an example.
}
Ieshaan Saxena
źródło
0

Nieco innym podejściem (przynajmniej na Androidzie) jest użycie adnotacji IntDef do połączenia zestawu stałych int

@IntDef({NOTAX, SALESTAX, IMPORTEDTAX})
@interface TAX {}
int NOTAX = 0;
int SALESTAX = 10;
int IMPORTEDTAX = 5;

Użyj jako parametru funkcji:

void computeTax(@TAX int taxPercentage){...} 

lub w deklaracji zmiennej:

@TAX int currentTax = IMPORTEDTAX;
mir
źródło