Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Перечисления (enum)

Иногда переменная может принимать лишь несколько заранее известных значений: дни недели, размеры одежды, статусы заказа. Хранить их строками рискованно — опечатку компилятор не заметит. Перечисление (enum) задаёт такой набор как отдельный тип.

Объявление перечисления

Значения перечисления называют константами и пишут заглавными буквами через запятую:

enum Size {
    SMALL, MEDIUM, LARGE
}
 
void main() {
    Size size = Size.MEDIUM;
    IO.println(size);
}

Результат:

MEDIUM

Переменной типа Size можно присвоить только одну из трёх констант — ничего другого компилятор не пропустит.

Сравнение и switch

Каждая константа существует в одном экземпляре, поэтому сравнивать их можно через ==. Перечисления удобно разбирать в switch:

enum Status {
    NEW, PAID, SHIPPED
}
 
String describe(Status status) {
    return switch (status) {
        case NEW -> "Заказ создан";
        case PAID -> "Заказ оплачен";
        case SHIPPED -> "Заказ отправлен";
    };
}
 
void main() {
    Status status = Status.PAID;
    IO.println(status == Status.PAID);
    IO.println(describe(status));
}

Результат:

true
Заказ оплачен

В case имя константы пишут без префикса Status.. Если перечислены все константы, ветка default не нужна.

Все значения

Метод values() возвращает массив всех констант по порядку объявления, ordinal() — номер константы с нуля, а name() — её имя строкой:

enum Size {
    SMALL, MEDIUM, LARGE
}
 
void main() {
    for (Size s : Size.values()) {
        IO.println(s.ordinal() + ": " + s.name());
    }
}

Результат:

0: SMALL
1: MEDIUM
2: LARGE

На номер ordinal() опасно полагаться при сохранении данных, а для словарей и множеств из констант есть EnumMap и EnumSet — см. урок коллекции для перечислений.

Поля, конструктор и методы

Перечисление — это класс, поэтому у него могут быть поля, конструктор и методы. Аргументы конструктора указывают в скобках после каждой константы:

enum Coin {
    CENT(1), NICKEL(5), DIME(10);
 
    private final int cents;
 
    Coin(int cents) {
        this.cents = cents;
    }
 
    int cents() {
        return cents;
    }
}
 
void main() {
    int total = 0;
    for (Coin coin : Coin.values()) {
        total += coin.cents();
    }
    IO.println("Сумма: " + total + " центов");
}

Результат:

Сумма: 16 центов

После последней константы в таком случае ставят точку с запятой.

Из строки в константу

Метод valueOf() находит константу по её имени. Это пригодится, когда значение приходит из файла или ввода пользователя:

enum Size {
    SMALL, MEDIUM, LARGE
}
 
void main() {
    Size size = Size.valueOf("LARGE");
    IO.println(size.ordinal());
}

Результат:

2

Частая ошибка

valueOf() ищет точное совпадение с учётом регистра. Если такой константы нет, программа падает с исключением:

enum Size {
    SMALL, MEDIUM, LARGE
}
 
void main() {
    Size size = Size.valueOf("large");
}

Результат:

Exception in thread "main" java.lang.IllegalArgumentException: No enum constant Main.Size.large

Приводите строку к нужному виду заранее — Size.valueOf(text.toUpperCase()) — и будьте готовы к неверному вводу.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.