Преобразование из enum-ординала в тип enums

У меня есть тип enums ReportTypeEnum который передается между методами во всех моих classах, но затем мне нужно передать это по URL-адресу, поэтому я использую порядковый метод для получения значения int. После того, как я получу его на другой странице JSP, мне нужно преобразовать его обратно в ReportTypeEnum чтобы я мог продолжить его передачу.

Как преобразовать порядковый номер в ReportTypeEnum ?

Использование Java 6 SE.

Чтобы преобразовать порядковый номер в его перечисление enum, вы можете сделать это:

 ReportTypeEnum value = ReportTypeEnum.values()[ordinal]; 

Обратите внимание на границы массива.

Обратите внимание, что каждый вызов values() возвращает вновь клонированный массив, который может негативно повлиять на производительность. Вы можете захотеть кэшировать массив, если он будет вызван часто.

Пример кода о том, как кэшировать values() .


Этот ответ был отредактирован, чтобы включить отзывы, приведенные в комментариях

Это почти наверняка плохая идея . Конечно, если ординал де-факто сохраняется (например, потому, что кто-то заклалвил URL-адрес) – это означает, что вы всегда должны сохранять порядок enum в будущем, что может быть неочевидным для того, чтобы скомпилировать сопровождающих.

Почему бы не закодировать enum используя myEnumValue.name() (и декодировать через ReportTypeEnum.valueOf(s) )?

Если я буду использовать values() много:

 enum Suit { Hearts, Diamonds, Spades, Clubs; public static final Suit values[] = values(); } 

Между тем везде, где: java:

 Suit suit = Suit.values[ordinal]; 

Обратите внимание на границы массива.

Вы можете использовать статическую таблицу поиска:

 public enum Suit { spades, hearts, diamonds, clubs; private static final Map lookup = new HashMap(); static{ int ordinal = 0; for (Suit suit : EnumSet.allOf(Suit.class)) { lookup.put(ordinal, suit); ordinal+= 1; } } public Suit fromOrdinal(int ordinal) { return lookup.get(ordinal); } } 

Я согласен с большинством людей, что использование ординала – это, вероятно, плохая идея. Обычно я решаю эту проблему, предоставляя enum частному конструктору, который может взять, например, значение DB, а затем создать статическую функцию fromDbValue аналогичную той, что была в ответе Яна.

 public ReportTypeEnum { R1(1), R2(2), R3(3), R4(4), R5(5), R6(6), R7(7), R8(8); private static Logger log = LoggerFactory.getLogger(ReportEnumType.class); private static Map lookup; private Integer dbValue; private ReportTypeEnum(Integer dbValue) { this.dbValue = dbValue; } static { try { ReportTypeEnum[] vals = ReportTypeEnum.values(); lookup = new HashMap(vals.length); for (ReportTypeEnum rpt: vals) lookup.put(rpt.getDbValue(), rpt); } catch (Exception e) { // Careful, if any exception is thrown out of a static block, the class // won't be initialized log.error("Unexpected exception initializing " + ReportTypeEnum.class, e); } } public static ReportTypeEnum fromDbValue(Integer dbValue) { return lookup.get(dbValue); } public Integer getDbValue() { return this.dbValue; } } , public ReportTypeEnum { R1(1), R2(2), R3(3), R4(4), R5(5), R6(6), R7(7), R8(8); private static Logger log = LoggerFactory.getLogger(ReportEnumType.class); private static Map lookup; private Integer dbValue; private ReportTypeEnum(Integer dbValue) { this.dbValue = dbValue; } static { try { ReportTypeEnum[] vals = ReportTypeEnum.values(); lookup = new HashMap(vals.length); for (ReportTypeEnum rpt: vals) lookup.put(rpt.getDbValue(), rpt); } catch (Exception e) { // Careful, if any exception is thrown out of a static block, the class // won't be initialized log.error("Unexpected exception initializing " + ReportTypeEnum.class, e); } } public static ReportTypeEnum fromDbValue(Integer dbValue) { return lookup.get(dbValue); } public Integer getDbValue() { return this.dbValue; } } 

Теперь вы можете изменить порядок, не изменяя поиск, и наоборот.

Это то, что я использую. Я не претендую на то, что он намного менее эффективен, чем более простые решения выше. То, что он делает, – это предоставить гораздо более четкое сообщение об исключении, чем «ArrayIndexOutOfBounds», когда неверное порядковое значение используется в вышеприведенном решении.

Он использует тот факт, что enumSet javadoc указывает, что iterator возвращает элементы в их естественном порядке. Есть утверждение, если это неверно.

Тест JUnit4 демонстрирует, как он используется.

  /** * convert ordinal to Enum * @param clzz may not be null * @param ordinal * @return e with e.ordinal( ) == ordinal * @throws IllegalArgumentException if ordinal out of range */ public static  > E lookupEnum(Class clzz, int ordinal) { EnumSet set = EnumSet.allOf(clzz); if (ordinal < set.size()) { Iterator iter = set.iterator(); for (int i = 0; i < ordinal; i++) { iter.next(); } E rval = iter.next(); assert(rval.ordinal() == ordinal); return rval; } throw new IllegalArgumentException("Invalid value " + ordinal + " for " + clzz.getName( ) + ", must be < " + set.size()); } @Test public void lookupTest( ) { java.util.concurrent.TimeUnit tu = lookupEnum(TimeUnit.class, 3); System.out.println(tu); } 
 public enum Suit implements java.io.Serializable, Comparable{ spades, hearts, diamonds, clubs; private static final Suit [] lookup = Suit.values(); public Suit fromOrdinal(int ordinal) { if(ordinal< 1 || ordinal> 3) return null; return lookup[value-1]; } } 

class испытаний

 public class MainTest { public static void main(String[] args) { Suit d3 = Suit.diamonds; Suit d3Test = Suit.fromOrdinal(2); if(d3.equals(d3Test)){ System.out.println("Susses"); }else System.out.println("Fails"); } } 

Я ценю, что вы делитесь с нами, если у вас более эффективный код. Мое перечисление огромно и постоянно называется тысячи раз.

Предположим, у вас есть следующее перечисление:

 public enum ErrorCodes { BUSINESS_ERROR(100), SERVER_ERROR(500), NETWORK_ERROR(1000); } 

По умолчанию вы не сможете получить экземпляр ErrorCode по его числовому значению, поскольку java не предоставляет никакого способа получить экземпляр Enum с помощью поля.

Для этого я обычно выставляю статический hash-файл внутри classа Enum, который сопоставляет каждое значение с соответствующим экземпляром Enum следующим образом:

 public enum ErrorCodes { BUSINESS_ERROR(100), SERVER_ERROR(500), NETWORK_ERROR(1000); private int errorCode; private static Map errorCodeByErrorNumber = new HashMap(); static { for (ErrorCodes errorCode : ErrorCodes.values()) { errorCodeByErrorNumber.put(errorCode.getErrorCode(), errorCode); } } private ErrorCodes(int errorCode) { this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } public static ErrorCodes getErrorCodeByNumber(Integer errorNumber) { return errorCodeByErrorNumber.get(errorNumber); } } 

Для более общих операций Enum проверьте следующее: Как использовать Enums в java

Это то, что я делаю на Android с Proguard:

 public enum SomeStatus { UNINITIALIZED, STATUS_1, RESERVED_1, STATUS_2, RESERVED_2, STATUS_3;//do not change order private static SomeStatus[] values = null; public static SomeStatus fromInteger(int i) { if(SomeStatus.values == null) { SomeStatus.values = SomeStatus.values(); } if (i < 0) return SomeStatus.values[0]; if (i >= SomeStatus.values.length) return SomeStatus.values[0]; return SomeStatus.values[i]; } } 

это коротко, и мне не нужно беспокоиться о том, что в Proguard есть исключение

Каждое перечисление имеет имя (), которое дает строку с именем члена enums.

Учитывая enum Suit{Heart, Spade, Club, Diamond} , Suit.Heart.name() даст Heart .

Каждое перечисление имеет метод valueOf() , который принимает тип enums и строку для выполнения обратной операции:

Enum.valueOf(Suit.class, "Heart") возвращает Suit.Heart .

Почему кто-то будет использовать ординалы вне меня. Это может быть на наносекунды быстрее, но это небезопасно, если члены enums изменяются, поскольку другой разработчик может не знать, что какой-то код использует порядковые значения (особенно на странице JSP, указанной в вопросе, сетевые и базовые служебные данные полностью доминируют над время, не используя целое число над строкой).

  • Синхронизация против блокировки
  • Как переключаться между кадрами в Selenium WebDriver с помощью Java
  • Включение внешних jar-файлов в новую сборку jar-файлов с Ant
  • Обновите ярлык с помощью таймера качания
  • Строка s = новая строка ("xyz"). Сколько объектов было сделано после выполнения этой строки кода?
  • gson выбрасывает MalformedJsonException
  • Отражение Java: как получить значение поля от объекта, не зная его classа
  • Как получить последний сегмент пути uri
  • Почему LinkedHashSet расширяет HashSet и реализует Set
  • Как разбить String на некоторый разделитель, но не удаляя этот разделитель в Java?
  • «Заполнить» символы Юникода в ярлыках
  • Interesting Posts

    Что произойдет, если я оставлю выключенный ноутбук под прямым солнечным светом в течение нескольких часов?

    Как преодолеть предел classа Case Scala из 22 полей?

    Получите исходные файлы jar, прикрепленные к Eclipse для зависимых от Maven зависимостей

    Отключить программы тайны, запущенные при запуске

    переключатель контекста streamа и переключатель контекста процесса

    Какие кодеки наиболее подходят для воспроизведения с помощью Windows Media Player в Windows XP?

    Начальная емкость вектора в C ++

    Найдите пути между двумя заданными узлами?

    Клавиатура MacBook Pro – как заменить / переустановить клавиши?

    В чем разница между упорядоченной и сортированной коллекцией?

    Windows Phone 8.1 Universal App завершается при переходе со второй страницы?

    Чрезмерное торрентирование и здоровье жесткого диска

    SQL Pivot от бедного человека. Список вопросов как столбцов и ответов на пользователя в одной строке

    Несколько сетевых интерфейсов на одном сетевом адаптере в Windows

    Как изменить изображения по умолчанию CheckBox

    Давайте будем гением компьютера.