JavaRush /Java блог /Random UA /Перетворення Enum на String

Перетворення Enum на String

Стаття з групи Random UA
Сьогодні поговоримо про роботу з рядковими перерахуваннями, а конкретніше з enumкласами, в яких організовано взаємодію з рядковими константами. Перетворення Enum на String - 1

Використання рядкових перерахувань

Під час розробки програми періодично необхідно оперувати фіксованим набором рядкових значень. Це може бути будь що. Наприклад, список колірних кодів, що підтримуються програмою, або список пристроїв з якими здатна взаємодіяти наша програма, пори року і т.д. Усе це — зумовлений набір рядкових констант із загальною структурою, із якими необхідно налагодити програмне взаємодія лише на рівні 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- локальне для розробки та дебагу
А також 4 URL для кожного з цих оточень. Звернемо увагу на деякі важливі моменти.
  1. Кожна URL-адресаа — це рядкова константа нашого переліку: вони визначаються в дужках у кожної enumконстанти.
  2. Обов'язково наявність конструктора, який приймає аргумент того самого типу, що й кожна enumконстанта.
  3. Область видимості конструктора - privateабо package private.
  4. Необхідно визначити змінну — поле класу, яке зберігатиме певні строкові константи. Для цього поля необхідно створити метод геттер, щоб використовувати значення рядкових констант ззовні.

Перебір рядкових перерахувань

На цьому етапі ми можемо перебрати всі доступні 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вже на першій лекції п'ятого рівня . Перетворення Enum на String - 2
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ