Сьогодні поговоримо про роботу з рядковими перерахуваннями, а конкретніше з
![Перетворення Enum на String - 2]()
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;
}
} У даному класі ми визначабо 4 оточення:
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<String, Environment> 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вже на першій лекції п'ятого рівня . 
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ