При работе с переменными / параметрами, которые могут принимать только конечное количество значений, я стараюсь всегда использовать Java enum
, как в
public enum BonusType {
MONTHLY, YEARLY, ONE_OFF
}
Пока я остаюсь внутри своего кода, все работает нормально. Однако мне часто нужно взаимодействовать с другим кодом, который использует простые int
(или String
) значения для той же цели, или мне нужно читать / писать из / в базу данных, где данные хранятся в виде числа или строки.
В этом случае я хотел бы иметь удобный способ связать каждое значение перечисления с целым числом, чтобы я мог преобразовывать оба способа (другими словами, мне нужно «обратимое перечисление»).
Перейти от enum к int очень просто:
public enum BonusType {
public final int id;
BonusType(int id) {
this.id = id;
}
MONTHLY(1), YEARLY(2), ONE_OFF(3);
}
Затем я могу получить доступ к значению int как BonusType x = MONTHLY; int id = x.id;
.
Однако я не вижу хорошего пути для обратного, то есть перехода от int к enum. В идеале что-то вроде
BonusType bt = BonusType.getById(2);
Единственные решения, которые я мог придумать:
- Поместите в перечисление метод поиска, который использует
BonusType.values()
для заполнения карты «int -> enum», затем кэширует его и использует для поиска. Будет работать, но мне придется копировать этот метод идентично в каждое используемое мной перечисление :-(. - Поместите метод поиска в статический служебный класс. Тогда мне понадобится только один метод поиска, но мне придется возиться с отражением, чтобы заставить его работать для произвольного перечисления.
Оба метода кажутся ужасно неудобными для такой простой (?) Задачи.
Любые другие идеи / идеи?
источник
ordinal()
.ordinal()
), или они определяются внешними силами?Ответы:
http://www.javaspecialists.co.za/archive/Issue113.html
Решение начинается так же, как ваше, со значения int как части определения перечисления. Затем он переходит к созданию универсальной поисковой утилиты:
Это хорошее решение, которое не требует «возни с отражением», потому что оно основано на том факте, что все типы перечислений неявно наследуют интерфейс Enum.
источник
Number
вместоByte
, потому что моя поддерживающая стоимость может быть больше по размеру.enum → int
int → перечисление
Строка → перечисление
перечисление → Строка
Примечание:
как вы правильно заметили,
ordinal()
от версии к версии она может быть "нестабильной". Это точная причина, по которой я всегда храню константы как строки в своих базах данных. (На самом деле, при использовании MySql я сохраняю их как перечисления MySql !)источник
BonusType.valueOf("MONTHLY")
)ordinal()
кажется мне проблемным решением, потому что оно сломается, когда список значений перечисления будет переставлен или значение будет удалено. Кроме того, это практично, только если значения int равны 0 ... n (что я часто обнаруживал, что это не так).values()
массива будет работать, только если все ваши значения имеют индекс 0 для своего идентификатора и объявлены по порядку. (Я проверил это, чтобы убедиться, что если выFOO(0), BAR(2), BAZ(1);
values[1] == BAR
values[2] == BAZ
double
).Я нашел это в сети, это было очень полезно и просто реализовать. Это решение было сделано НЕ мной
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
}
источник
Кажется, что ответы на этот вопрос устарели с выпуском Java 8.
источник
Collectors.toMap()
должен бытьFunctions.identity()
вместоnull
?org.apache.commons.lang.enums.ValuedEnum;
Чтобы избавить меня от написания большого количества шаблонного кода или дублирования кода для каждого Enum, я
ValuedEnum
вместо этого использовал Apache Commons Lang .Определение :
Использование:
int -> ValuedEnum:
источник
Возможно, вы могли бы использовать что-то вроде
Это уменьшит необходимость отражения в вашем служебном классе.
источник
В этом коде для постоянного и интенсивного поиска есть память или процесс для использования, и я выбираю память с массивом преобразователя в качестве индекса. Надеюсь, это поможет
источник
Используйте интерфейс, чтобы показать, кто здесь главный.
И результат:
источник
Оба
.ordinal()
иvalues()[i]
являются нестабильными, поскольку они зависят от порядка перечислений. Таким образом, если вы измените порядок перечислений или добавите / удалите некоторые, ваша программа сломается.Вот простой, но эффективный метод сопоставления enum и int.
Применить его к струнам не составит труда.
источник
Шаг 1 Определите
interface
EnumConverterШаг 2
Создайте имя класса ReverseEnumMap
Шаг 3
Перейти к вам
Enum
класс иimplement
это сEnumConverter<ContentType>
и методов коррекции интерфейса курса. Вам также необходимо инициализировать статический ReverseEnumMap.Шаг 4
Теперь создайте
Communication
файл класса и вызовите его новый метод для преобразованияEnum
вString
иString
вEnum
. Я только что поставил основной метод для объяснения.Нажмите, чтобы увидеть полное объяснение
источник
ContentType convert(String pKey)
статический, который устраняет необходимость вCommunication
классе и мне больше нравится. +1Я не уверен, что это то же самое в Java, но типы перечислений в C также автоматически сопоставляются с целыми числами, поэтому вы можете использовать либо тип, либо целое число для доступа к нему. Вы уже пробовали просто получить к нему доступ с помощью целого числа?
источник
.ordinal()
метода. (Другой способ - использоватьBonusType.values()[i]
.) Но в приведенном выше примере индексы здесь и внешние значения не совпадают.Действительно отличный вопрос :-) Некоторое время назад я использовал решение, похожее на решение мистера Фергюсона. Наше декомпилированное перечисление выглядит так:
Видя это, становится очевидным, почему
ordinal()
он нестабилен. Этоi
вsuper(s, i);
. Я также пессимистичен, что вы можете придумать более элегантное решение, чем те, которые вы уже перечислили. Ведь перечисления - это классы, как любые конечные классы.источник
Для полноты, вот общий подход к извлечению значений перечисления по индексу из любого типа перечисления. Я намеревался сделать так, чтобы метод выглядел как Enum.valueOf (Class, String) . Fyi, я скопировал этот метод отсюда .
Вопросы, связанные с индексом (уже подробно обсуждаемые здесь), все еще актуальны.
источник
MyEnumType.values()
- нет необходимости в статическом вспомогательном методе.источник
Мне нужно было что-то другое, потому что я хотел использовать общий подход. Я читаю перечисление байтовых массивов и обратно. Вот где я придумал:
Пример перечисления:
}
источник
Просто потому, что принятый ответ не самодостаточен:
Код поддержки:
Пример использования:
источник
дано:
общедоступное перечисление BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}
BonusType бонус = ГОД;
System.out.println (Bonus.Ordinal () + ":" + бонус)
Выход: 1: ГОД
источник
Если у вас классная машина
А свойство Color - это класс
И вы хотите преобразовать Color в Enum
Просто добавьте метод в класс Color для преобразования Color в ColorEnum
а внутри ColorEnum реализует метод getById ()
Теперь вы можете использовать classMap
источник