Перечисления (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()) — и будьте готовы к неверному вводу.