Преобразование строки в элемент enum
Только я получаю его как String, а нужно что бы вернул типа enum PriorityType. Как выкрутиться из этой ситуации?
Отслеживать
23.4k 3 3 золотых знака 49 49 серебряных знаков 70 70 бронзовых знаков
задан 10 апр 2015 в 6:06
duddeniska duddeniska
3,958 17 17 золотых знаков 67 67 серебряных знаков 113 113 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Для преобразования строки в элемент enum в каждом enum’е есть метод valueOf :
PriorityType high = PriorityType.valueOf("HIGH");
Этот метод чувствителен к регистру, передаваемая строка должна в точности повторять имя элемента enum’а.
Ещё один вариант, позволяющий кастомизировать строки, на основании которых создаются элементы enum’а. Он строится на основе использования конструктора и реализации своего метода преобразования строки в елемент enum’а:
public enum PriorityType < LOW("LowPrioroty"), MIDDLE("MiddlePrioroty"), HIGH("HighPrioroty"); private String value; private PriorityType(String value) < this.value = value; >public static PriorityType fromString(String value) < if (value != null) < for (PriorityType pt : PriorityType.values()) < if (value.equalsIgnoreCase(pt.value)) < return pt; >> > throw new IllegalArgumentException("No such value"); > > PriorityType low = PriorityType.fromString("lowpriority");
Преобразование Enum в String


Сегодня поговорим о работе со строковыми перечислениями, а конкретнее — с enum классами, в которых организовано взаимодействие со строковыми константами.
Использование строковых перечислений
Во время разработки приложения периодически нужно оперировать фиксированным набором строковых значений. Это может быть что угодно. Например, список цветовых кодов, поддерживаемых приложением, или список устройств с которыми способно взаимодействовать наше приложение, времена года и т.д. Все это — предопределенный набор строковых констант с общей структурой, с которыми необходимо наладить программное взаимодействие на уровне Java кода. Когда необходимо взаимодействовать с предопределенным набором строковых (и не только) констант, лучшее решение — написать свой enum класс. Ниже рассмотрим примеры преобразования enum в string .
Создание строковых перечислений
Создадим enum класс, в котором хранится список различных окружений для развертывания приложения, а также URL каждого окружения:
public enum Environment < PROD("https://release.application.com/"), TEST("https://test.application.com/"), AUTO_TEST("https://autotest.application.com/"), DEV("http://localhost:8080"); private final String url; Environment(String url) < this.url = url; >public String getUrl() < return url; >>
- PROD — релизное
- TEST — для ручного тестирования
- AUTO_TEST — окружение для автотестов
- DEV — локальное для разработки и дебага
- Каждый URL — это строковая константа нашего перечисления: они определяются в скобках у каждой enum константы.
- Обязательно наличие конструктора, принимающего аргумент того же типа, что и каждая enum константа.
- Область видимости конструктора — private либо package private .
- Необходимо определить переменную — поле класса, которое будет хранить определенные нами строковые константы. Для этого поля необходимо создать метод геттер, чтобы использовать значения строковых констант извне.
Перебор строковых перечислений
На данном этапе мы уже можем перебрать все доступные enum значения, а также получить привязанные к ним строковые константы. Чтобы получить все значения любого enum класса, необходимо использовать метод values() :
public class Main < public static void main(String[] args) < for (Environment env : Environment.values()) < System.out.println(env + " : " + env.getUrl()); >> >
Вывод:
PROD : https://release.application.com/ TEST : https://test.application.com/ AUTO_TEST : https://autotest.application.com/ DEV : http://localhost:8080
Как видно из примера, для вывода на печать имени enum константы мы передали ее в метод System.out.println , а для вывода на печать привязанного к данной константе url мы использовали определенный нами геттер.
Получение строковой константы из enum
Для получения значения любой строковой константы мы также можем вызывать геттер у любой enum константы:
public class Main < public static void main(String[] args) < String prodUrl = Environment.PROD.getUrl(); String devUrl = Environment.DEV.getUrl(); System.out.println("Production url is: " + prodUrl); System.out.println("Development url is: " + devUrl); >>
Вывод:
Production url is: https://release.application.com/ Development url is: http://localhost:8080
Получение enum константы по имени
Порой бывает необходимо получить enum константу по ее строковому наименованию. Делается это с помощью метода valueOf(String) , который возвращает константу по ее имени:
public class Main < public static void main(String[] args) < Environment prod = Environment.valueOf("PROD"); Environment dev = Environment.valueOf("DEV"); System.out.println("Production url is: " + prod.getUrl()); System.out.println("Development url is: " + dev.getUrl()); >>
Вывод:
Production url is: https://release.application.com/ Development url is: http://localhost:8080
Но тут нужна осторожность. Если метод не найдет enum константу с указанным именем, будет брошено исключение java.lang.IllegalArgumentException .
Преобразование String в Enum
Иногда возникает обратная потребность. Зная значение enum , получить саму enum константу. Т.е. в нашем примере, зная определенный адрес, нужно получить соответствующую ему Environment константу. Есть несколько вариантов сделать это. И все они требуют доработки в самом enum классе. Вариант 1. Перебор внутри класса. Необходимо создать метод, который будет принимать строку, и сравнивать ее со всеми значениями enum класса. При совпадении метод будет возвращать нужное перечисление. Для нашего примера необходимо внутри класса Environment создать следующий метод:
public static Environment getEnvByUrl(String url) < for (Environment env : values()) < // либо equalsIgnoreCase, на ваше усмотрение if (env.getUrl().equals(url)) < return env; >> // Либо просто вернуть null throw new IllegalArgumentException("No enum found with url: [" + url + "]"); >
Тогда мы сможем получать enum из строки таким образом:
public class Main < public static void main(String[] args) < String url = "http://localhost:8080"; Environment env = Environment.getEnvByUrl(url); System.out.println("Environment name for url=[" + url + "] is: " + env); >>
Environment name for url=[http://localhost:8080] is: DEV
У этого подхода есть свои минусы. Каждый раз для получения enum константы придется перебирать все значения и производить некоторое количество сравнений. Ущерб производительности в таком случае будет определяться количеством констант и количеством подобных операций. У второго способа решения этой задачи такой проблемы нет. Полный код Enum класса:
public enum Environment < PROD("https://release.application.com/"), TEST("https://test.application.com/"), AUTO_TEST("https://autotest.application.com/"), DEV("http://localhost:8080"); private final String url; Environment(String url) < this.url = url; >public String getUrl() < return url; >public static Environment getEnvByUrl(String url) < for (Environment env : values()) < if (env.getUrl().equals(url)) < return env; >> throw new IllegalArgumentException("No enum found with url: [" + url + "]"); > >
Вариант 2. Использование HashMap В этом случае мы создаем карту внутри нашего перечисления и заполняем ее один раз на этапе компиляции, а затем берем из нее значения:
public enum Environment < PROD("https://release.application.com/"), TEST("https://test.application.com/"), AUTO_TEST("https://autotest.application.com/"), DEV("http://localhost:8080"); private final String url; Environment(String url) < this.url = url; >public String getUrl() < return url; >// Создаем static final карту private static final Map LOOKUP_MAP = new HashMap<>(); // Заполняем её всеми значениями static < for (Environment env : values()) < LOOKUP_MAP.put(env.getUrl(), env); >> // Возвращаем Environment по строковому url public static Environment getEnvByUrl(String url) < return LOOKUP_MAP.get(url); >>
В плане использования оба варианта идентичны:
public class Main < public static void main(String[] args) < String url = "http://localhost:8080"; Environment env = Environment.getEnvByUrl(url); System.out.println("Environment name for url=[" + url + "] is: " + env); >>
Environment name for url=[http://localhost:8080] is: DEV

Но и у этого способа есть недостатки. Во-первых, кода стало значительно больше. А во-вторых, HashMap со всеми enum значениями будет храниться в памяти приложения постоянно. Как видим, у всего есть плюсы и минусы. Но учитывая то, что в enum классах обычно хранится не так уж много значений, минусы будут практически незаметны. Есть нюанс: если подобная операция (получение в Java Enum по String значению) выполняется часто, лучше использовать второй вариант. Подробнее с данной темой и Enum классами вообще можно познакомиться на курсе JavaRush. Студенты JavaRush изучают Enum уже на первой лекции пятого уровня.
Новый тип данных – enum: перечисление
Сегодня мы изучим еще одну разновидность типов данных в Java — enum . Название enum происходит от слова Enumeration — перечисление. Что же это за тип данных и с чем его едят?
Иногда в работе программиста возникает необходимость создать новый тип данных, переменные которого принимают только значения из небольшого фиксированного списка.
Например, тип ДеньНедели может принимать только значения ПОНЕДЕЛЬНИК , ВТОРНИК , СРЕДА , . Всего 7 значений. Или тип Месяц может принимать только значения ЯНВАРЬ , ФЕВРАЛЬ , МАРТ , . Всего 12 значений.
Можно, конечно, использовать числа (тип int ): 1 — понедельник, 2 — вторник и т.д. Но кто-то случайно может присвоить такой переменной значение 8 , или, например, значение 0 .
Легко может возникнуть ситуация, когда один программист думает, что дни недели (или месяцы) нумеруются с нуля, другой — что с единицы и т.д.
Поэтому в Java придумали тип данных, который состоит из конечного набора значений — enum .
2. Объявление типа
Выглядит объявление нового enum типа данных так:
enum ИмяТипа < ЗНАЧЕНИЕ1, ЗНАЧЕНИЕ2, ЗНАЧЕНИЕ3 >
Где ИмяТипа — это имя нового типа (класса), а в скобках через запятую перечислены возможные значения: Значение1 , Значение2 , Значение3 .
Давайте ради примера создадим свой enum для типа ДеньНедели :
enum Day
Присваивать значения переменным этого типа можно таким образом:
Day day = Day.MONDAY;
Day day = Day.FRIDAY; System.out.println(day);
FRIDAY
3. Методы enum ’а
Тип enum имеет несколько встроенных методов, два из них очень интересные:
Статический метод values() возвращает массив всех значений типа enum :
Day[] days = Day.values(); for (Day day: days) System.out.println(day); System.out.println(days[2]);
Выводим содержимое массива на экран:
MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY SUNDAY WEDNESDAY
Метод ordinal() возвращает порядковый номер константы. Вызывать его нужно не у класса enum , а у значения enum :
System.out.println(Day.MONDAY.ordinal()); System.out.println(Day.FRIDAY.ordinal()); System.out.println(Day.SUNDAY.ordinal());
0 4 6
4. Преобразование в класс
На самом деле никакой магии тут нет, и компилятор просто подсыпал нам немного синтаксического сахара. Во время компиляции класс enum Day будет преобразован в обычный класс:
public class Day < public static final Day MONDAY = new Day(0); public static final Day TUESDAY = new Day(1); public static final Day WEDNESDAY = new Day(2); public static final Day THURSDAY = new Day(3); public static final Day FRIDAY = new Day(4); public static final Day SATURDAY = new Day(5); public static final Day SUNDAY = new Day(6); private static final Day[] array = ; private final int value; private Day (int value) < this.value = value; > public int ordinal() < return this.value; > public static Day[] values() < return array; > >
Список статических констант-значений
Массив со всеми значениями типа Day
Переменная со значением конкретного объекта Day
private конструктор класса Day — объекты класса Day можно создавать только внутри класса Day .
Метод ordinal нужно вызвать у объекта Day .
Он возвращает значение объекта — value .
Если убрать из класса Day все статические методы и переменные, мы получим такую картину:
public class Day < private int value; private Day (int value) < this.value = value; > public int ordinal() < return this.value; > >
Переменная value хранит значение объекта Day
Объекты Day можно создавать только внутри класса Day — конструктор private .
Т.е. в принципе ничего страшного тут не происходит. Компилятор создает класс Day , затем добавляет в него константы, которые были значениями у enum , добавляет недостающие методы и делает конструктор класса private . Как работают конструкторы, мы разберем немного позднее.
Теперь, думаем, понятно, почему мы заносим значение в переменную таким образом:
Day day = Day.MONDAY;
MONDAY — это просто статическое поле (константа) класса Day . А при обращении к статическим методам и полям извне класса перед именем поля или метода нужно указывать имя класса.
5. Еще методы enum ’а
Еще у всех enum -классов есть несколько интересных особенностей.
Преобразование в строку и обратно
Чтобы преобразовать объект типа enum в строку, у него нужно вызвать метод toString() .
String str = Day.MONDAY.toString();
Для обратного преобразования (строки в объект Day ) можно воспользоваться статическим методом valueOf() :
Day day = Day.valueOf("MONDAY");
Очень удобно и полезно во многих случаях.
Преобразование в число и обратно
Как преобразовать объект типа enum в число, вы уже знаете: для этого нужно вызвать метод ordinal() :
int index = Day.MONDAY.ordinal();
Для обратного преобразования (числа в объект Day ) нужно воспользоваться конструкцией подлиннее:
Day day = Day.values()[2];
Day day = Day.MONDAY; int index = day.ordinal(); Day newDay = Day.values()[index+2];
Важный момент, т.к. значения типа enum представляют собой фиксированный набор констант, их можно сравнивать через ==. Ну не может существовать двух одинаковых объектов MONDAY с разными ссылками. Каждый объект-значение типа enum существует только в единственном экземпляре. Поэтому сравнение переменных типа enum через == всегда будет работать.
6. Добавление своих методов в enum
Так как enum во время компиляции превращается в обычный класс, в нем можно объявлять методы: эти методы просто добавятся в класс, который сгенерирует компилятор. Например, мы хотим, чтобы наш enum Day возвращал не массив значений, а список.
Тогда в него можно дописать такой код:
enum Day < MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; public static ListDay> asList() < ArrayListDay> list = new ArrayListDay>(); Collections.addAll(list, values()); return list; > >
После списка значений нужно поставить точку с запятой.
Создаем объект ArrayList .
Теперь этот метод можно вызывать в коде:
List list = Day.asList();

Комментарии (180)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
SobolenkoE Уровень 19
5 января 2024
Только сейчас дошла отсылка в имени специалиста Андерсена, которого извлекают из матрицы.
Anastasia Frisman Уровень 15 Expert
27 декабря 2023
В последней задаче перед названием метода не забудьте написать тип возвращаемого значения — Month[] Я почему-то на этом споткнулась))
JIexa Уровень 16
15 декабря 2023

Задача: Четыре сезона Правая кнопка на директории задачи слева в структуре проекта — new — java class — enum
ExToozy Уровень 41
11 декабря 2023
Есть ещё один прикол с enum, так называемый супер enum, он делает так что при обращении , допустим Season.WINTER.toString будет выведено Зима, очень удобно получается
public enum Season < WINTER("Зима"), // SPRING("Осень"), SUMMER("Лето"), AUTUMN("Весна"); final String toString; // создаем значение в котором будет храниться наше текстовое определение Season(String toString) < this.toString = toString; // при создании экземпляра будет присваивать текстовое значение >>
Сергей Уровень 26
2 декабря 2023
public static Month[] getAutumnMonths()
Roman Уровень 17
23 ноября 2023
public static Month[] getWinterMonths() < Month[] tmp =
Viktoriya Уровень 29
20 ноября 2023
В задаче Четыре сезона, вывод должен быть в ручную, через foreach — не принимает валидатор.
Алексей Осипов Уровень 16
12 ноября 2023
for(JavarushQuest step: JavarushQuest.values())
Anatoly Уровень 25
23 сентября 2023
Andrey Уровень 16
23 августа 2023
Кто — то может доходчиво объяснить для чего это и куда это по факту добавляется? __________________________________________________________ Для обратного преобразования (строки в объект Day) можно воспользоваться статическим методом valueOf(): Day day = Day.valueOf(«MONDAY»); ____________________________________________________________________ Объяснение ниже с инпутом в качестве аргумента в valueOf тоже не прояснило ситуации. У нас же в enum записаны константы, которые для того и записаны именно в enum чтобы их не меняли, получается что MONDAY никуда не делся, и почему тогда просто не создать очередную переменную Day day = Day.MONDAY ? Или речь о том что мы абсолютно любую строку можем передать в valueOf, даже отсутствующую в перечислении? и что она добавится новой константой? «Для преобразования строки в объект Day» — и что мне с этим объектом делать и для чего приводить строку к типу Day? В примерах выше в классе enum day даже конструктора такого нет, какой нафиг объект класса Day, если по лекции, объекты Day создаются на основе перечисленных констант? Уймите пожалуйста душевные муки, объясните по человечески
Получение значения перечисления из строки в Java
Перечисления (enum) в Java — это специальный тип данных, который позволяет переменной быть набором предопределенных констант. Они часто используются для создания наборов значений, которые затем можно использовать для контроля работы программы.
Рассмотрим пример. Представим, что у нас есть перечисление Color , которое представляет различные цвета:
public enum Color
Допустим, у нас есть строка, которая содержит одно из этих значений, и мы хотим преобразовать эту строку в соответствующее значение перечисления. Например, если у нас есть строка «BLUE», мы хотим получить значение Color.BLUE .
В этом случае нам поможет метод Enum.valueOf() . Этот метод предназначен для преобразования строкового представления значения перечисления в само значение перечисления.
Использовать этот метод достаточно просто. Вот как мы можем получить значение перечисления Color из строки:
String colorString = "BLUE"; Color color = Color.valueOf(colorString);
В этом коде Color.valueOf(colorString) вернет значение Color.BLUE , которое соответствует строке «BLUE».
Таким образом, с помощью метода Enum.valueOf() можно легко получить значение перечисления из строки в Java. Однако стоит помнить, что если строка не совпадает ни с одним из значений перечисления, то будет выброшено исключение IllegalArgumentException . Поэтому перед использованием этого метода хорошей практикой будет проверить, содержит ли перечисление требуемое значение.