Как преобразовать значение enum в int?

240

У меня есть функция, которая возвращает тип int. Однако у меня есть только значение перечисления TAX.

Как я могу привести значение перечисления TAX к 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
источник
1
Возможный дубликат Как сопоставить int и enum
малат

Ответы:

354

Вам нужно было бы как- valueнибудь выставить enum , например

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

(Кстати, я изменил названия, чтобы они стали более привычными и удобочитаемыми.)

Это предполагает, что вы хотите значение, назначенное в конструкторе. Если это не то, что вы хотите, вам нужно дать нам больше информации.

Джон Скит
источник
1
@likejiujitsu: Это происходит в противоположном направлении. В этом вопросе OP уже имеет значение типа Taxи хочет получить из него числовое значение.
Джон Скит
Я только что попробовал это и понял, что это терпит неудачу, myEnumValue = MyEnum.valueOf(myInt);arg должен иметь тип String - или я что-то упускаю?
Likejudo
Это решение хуже, чем ничего. Кажется, перечисления в Java просто не должны использоваться? Или JDK 1.8 изменил это?
ebyrob
@ebyrob: Учитывая голосование, кажется, что многие люди не согласны с вами, как и я. Если вам нужен фиксированный набор значений, перечисления вполне подойдут.
Джон Скит
209

Я предпочитаю это:

public enum Color {

   White,

   Green,

   Blue,

   Purple,

   Orange,

   Red
}

затем:

//cast enum to int
int color = Color.Blue.ordinal();
vivia
источник
34
Это неверно / не рекомендуется Джошуа Блохом в его книге «Эффективная Java» (2-е изд). См. Пункт 31.
user504342
43
@ user504342 У меня нет 2-го издания книги, поэтому не могли бы вы объяснить, почему это не рекомендуется?
Likejudo
17
2 причины: во-первых, любая связь между порядковыми значениями и константами прекратится, если будут добавлены новые константы, и два документа API специально рекомендуют это.
jordanpg
8
Так чисто и идеально. Я вижу несколько "не делай этого" и "не рекомендуется". Мне придется выяснить, почему это считается плохим. Некоторые раздутые образцы выглядят плохо IMO. Так много работы, чтобы сделать такую ​​простую задачу.
Херб Михан
4
В команде вы уверены, что ваш со-разработчик добавит значение в середине (хуже в начале) или просто отсортирует их, потому что им нечего делать, и полностью испортит код, используя.ordinal()
Майкл Лаффарг,
18

Если вы хотите, чтобы значение, которое вы назначаете в конструкторе, вам нужно добавить метод в определение enum, чтобы вернуть это значение.

Если вам нужен уникальный номер, представляющий значение перечисления, вы можете использовать ordinal().

unholysampler
источник
2
Быть осторожен. Существует гораздо больше анти-паттернов развития, на которые опираются, ordinal()чем действительные варианты использования ordinal(). Если вам нужно сохранить уникальное значение для enum, то просто сохраните enum. Существуют EnumSets, Списки Enum, EnumMaps и почти любая другая коллекция Enum, которую вы можете захотеть получить.
Эдвин Бак
1
@ EdwinBuck: Хорошо отметить, я просто хотел упомянуть о существовании, ordinal()потому что ОП не давал понять, что он хочет, чтобы int был на самом деле.
unholysampler
Не получайте порядковый номер. Пожалуйста, проверьте enum api относительно этого. Голосование убрано.
Полное судно на воздушной подушке
3
Интересно, что думают люди об использовании ordinal()внутри самого перечисления? Например, у меня есть перечисление под названием « Season» , который содержит значение Spring, Summer, Autumnи Winter, и это не публичный метод называется next()возвращающим values()[(ordinal() + 1) % 4] Наружно, не код когда - нибудь увидит порядковый номер, и никогда не будут дополнительные членами в этом перечислении, так что это похоже на действительный вариант использования.
Даррел Хоффман
1
@DarrelHoffman У меня такое ощущение, что делать это хорошо, поскольку единственные веские аргументы, которые я вижу против использования ordinal()шарнира в далеко идущем коде, нарушаются из-за изменений в константах перечисления. Если вы собираетесь изменить константы перечисления, вы уже должны быть в этом файле. Большинство перечислений довольно короткие, и если это не так, вы все равно должны проверить файл более тщательно. В обоих случаях у вас, вероятно, next()все равно должен быть модульный тест, охватывающий ваш метод.
Алан Хенсли
12

Иногда какой-то подход C # облегчает жизнь в мире 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
источник
Для меня это самый желательный путь. Я получаю преимущества enum (ясности кода), типа данных, который удобен для БД, и мне не нужно исследовать 100 альтернатив enum, чтобы сделать это «способом Android». Просто и эффективно.
Джон Уорд
Ницца. Как будто java-перечисление просто совершенно не связано с реальностью того, для чего используется перечисление ... особенно, если люди тогда начинают злоупотреблять им для таких вещей, как одиночные игры. Этот подход имеет тот недостаток, что у него нет простого способа получить все значения.
Нергудс
Разве у этого нет недостатка в попытке передать значение enum методу? Вы больше не можете передавать XLINK методу, потому что он не представляет ничего конкретного. Вы теряете ввод в свой метод. Подпись метода должна быть короткой, а не XLINK.
Дастин Дженсен
2

Возможно, лучше использовать представление String, чем целое число, потому что String все еще действителен, если значения добавляются в перечисление. Вы можете использовать метод enum name () для преобразования значения перечисления в строку и метод перечисления valueOf () для повторного создания представления перечисления из строки. В следующем примере показано, как преобразовать значение перечисления в String и обратно (ValueType является перечислением):

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");
Майк
источник
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.
}
Иешаан Саксена
источник
0

Несколько иной подход (по крайней мере, для Android) заключается в использовании аннотации IntDef для объединения набора констант int

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

Использовать в качестве параметра функции:

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

или в объявлении переменной:

@TAX int currentTax = IMPORTEDTAX;
Mir
источник