1. Введение
В программировании часто приходится оперировать списками заранее известных, ограниченных вариантов. Например: дни недели, цвета светофора, уровни сложности игры, статусы заказа. Каждый из этих вариантов обычно представлен фиксированным значением. Вот тут мы и подбираемся ближе к нашей сегодняшней теме — перечислениям (enum).
Перечисление — это специальный тип данных, который позволяет объявлять набор именованных констант.
enum — как коробка с разложенными по ячейкам ярлыками, где каждый ярлык — уникальное имя, связанное с числом.
Главные плюсы enum:
- Ваш код становится читаемым и самодокументируемым;
- Вместо загадочных «магических чисел» вроде 0, 1, 2 появляются выразительные имена: DayOfWeek.MONDAY или TrafficLight.RED;
- Компилятор будет ругаться, если вы попытаетесь присвоить некорректное значение;
- За каждым элементом скрывается… обычное целое число! (Но к этому мы еще вернемся.)
Синтаксис объявления enum
// Общий шаблон объявления перечисления
public enum Имя
{
КОНСТАНТА1 ,
КОНСТАНТА2 ,
КОНСТАНТА3
}
Объявить перечисление в Java очень просто. Вот базовый пример:
// Файл DayOfWeek.java
public enum DayOfWeek {
MONDAY, // 0
TUESDAY, // 1
WEDNESDAY, // 2
THURSDAY, // 3
FRIDAY, // 4
SATURDAY, // 5
SUNDAY // 6
}
Пояснение:
- Ключевое слово enum говорит компилятору: «Это перечисление!»
- В фигурных скобках через запятую идут имена вариантов (констант).
- Принято писать имена в UPPER_SNAKE_CASE (все буквы заглавные, слова через подчёркивание).
Где можно объявлять enum?
- В отдельном файле (DayOfWeek.java).
- Внутри класса (если нужно сделать приватное перечисление только для этого класса).
- Даже внутри метода (но так делают редко).
2. Использование enum в коде
Объявление переменной enum:
DayOfWeek today = DayOfWeek.MONDAY;
Теперь today может принимать только одно из значений, объявленных в DayOfWeek.
Пример использования в switch
switch (today)
{
case MONDAY:
System.out.println("Ох, понедельник...");
break;
case FRIDAY:
System.out.println("Ура, пятница!");
break;
default:
System.out.println("Обычный день.");
}
Важное отличие: в case пишем просто имя константы (без префикса), если тип переменной уже известен компилятору.
Перебор всех значений enum
У каждого enum есть статический метод values(), который возвращает массив всех его значений:
for (DayOfWeek day : DayOfWeek.values())
{
System.out.println(day);
}
Это очень удобно для вывода меню, проверки, генерации вариантов и т.д.
3. Методы enum: name(), ordinal(), valueOf()
Перечисления в Java — не просто списки констант, а полноценные классы с методами!
Метод name()
Возвращает имя константы в виде строки (как оно написано в коде):
DayOfWeek day = DayOfWeek.FRIDAY;
System.out.println(day.name()); // "FRIDAY"
Метод ordinal()
Возвращает порядковый номер константы (счёт с нуля):
System.out.println(DayOfWeek.MONDAY.ordinal()); // 0
System.out.println(DayOfWeek.FRIDAY.ordinal()); // 4
Внимание: Не стоит хранить или сравнивать enum по ordinal(), если порядок может измениться в будущем! Лучше использовать имена.
Метод valueOf(String name)
Преобразует строку в значение enum, если такая константа существует:
DayOfWeek day = DayOfWeek.valueOf("MONDAY");
System.out.println(day); // MONDAY
Если строки не совпадают — будет выброшено исключение IllegalArgumentException.
Метод values()
Возвращает массив всех значений enum (уже был пример выше):
DayOfWeek[] days = DayOfWeek.values();
4. Enum с полями, конструктором и методами
Перечисления в Java можно расширять: добавлять поля, конструкторы, методы! Да, это не просто список имён, а мини-класс.
Пример: дни недели с локализованным названием
public enum DayOfWeek
{
MONDAY("Понедельник"),
TUESDAY("Вторник"),
WEDNESDAY("Среда"),
THURSDAY("Четверг"),
FRIDAY("Пятница"),
SATURDAY("Суббота"),
SUNDAY("Воскресенье");
private final String russianName;
// Конструктор (private по умолчанию)
DayOfWeek(String russianName)
{
this.russianName = russianName;
}
public String getRussianName()
{
return russianName;
}
}
Подробнее как это работает вы узнаете, когда мы начнем изучать ООП в уровнях 27+ :P
Теперь можно делать вот так:
DayOfWeek day = DayOfWeek.WEDNESDAY;
System.out.println(day.getRussianName()); // "Среда"
Фишка: У каждого значения enum свои данные (в данном случае — русское название).
Преимущества использования enum
- Безопасность типов: нельзя случайно присвоить переменной enum значение, которого нет в списке.
- Читаемость: код сам себя документирует (TrafficLight.RED вместо 1 или "red").
- Удобство поддержки: если нужно добавить или удалить вариант, делается это в одном месте.
- Работает с switch: enum идеально подходит для ветвлений по значениям.
- Можно расширять: добавлять поля, методы, реализовывать интерфейсы.
- Меньше ошибок: компилятор поможет не забыть обработать варианты (особенно в switch-конструкциях).
6. Практика: используем enum в нашем приложении
Давайте добавим в наше мини-приложение поддержку дней недели через enum.
Шаг 1. Объявим enum
public enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Шаг 2. Используем в коде
System.out.println("Введите день недели (например, MONDAY):");
Scanner console = new Scanner(System.in);
String input = console.nextLine().toUpperCase();
DayOfWeek day = DayOfWeek.valueOf(input);
switch (day)
{
case MONDAY:
System.out.println("Начало рабочей недели!");
break;
case FRIDAY:
System.out.println("Скоро выходные!");
break;
case SATURDAY:
case SUNDAY:
System.out.println("Ура, выходные!");
break;
default:
System.out.println("Обычный рабочий день.");
}
Что происходит:
- Пользователь вводит день недели (например, "monday" или "MONDAY").
- Преобразуем строку к верхнему регистру (toUpperCase()), чтобы не зависеть от регистра.
- Преобразуем строку в значение enum через valueOf.
- Используем switch для вывода разного сообщения.
- Если введено что-то не то — ловим ошибку и выводим предупреждение.
7. Типичные ошибки при работе с enum
Ошибка №1: Использование строк или чисел вместо enum. Очень часто начинающие программисты продолжают писать так:
int day = 1; // 1 — это понедельник?
или
String status = "DELIVERED";
Это плохо: можно ошибиться в написании, трудно поддерживать код. Используйте enum!
Ошибка №2: Сравнение enum через == и .equals(). В Java значения enum можно сравнивать через == — это безопасно, потому что все значения уникальны в рамках класса enum:
if (day == DayOfWeek.MONDAY) { ... } // ОК!
Хотя .equals() тоже работает, но чаще используют ==.
Ошибка №3: Плохие имена элементов enum. Не называйте элементы VALUE1, VALUE2, VALUE3 — через месяц никто не поймёт, что это значит! Используйте осмысленные имена.
Ошибка №4: Использование ordinal() для логики. Не пишите так:
if (day.ordinal() == 0) { ... } // Не надо!
Порядок элементов может измениться, и всё сломается. Используйте имена!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ