JavaRush/Курсы/JAVA 25 SELF/Перечисление: enum

Перечисление: enum

Открыта

1. Введение

В программировании часто приходится оперировать списками заранее известных, ограниченных вариантов. Например: дни недели, цвета светофора, уровни сложности игры, статусы заказа. Каждый из этих вариантов обычно представлен фиксированным значением. Вот тут мы и подбираемся ближе к нашей сегодняшней теме — перечислениям (enum).

Перечисление — это специальный тип данных, который позволяет объявлять набор именованных констант.

enum — как коробка с разложенными по ячейкам ярлыками, где каждый ярлык — уникальное имя, связанное с числом.

Главные плюсы enum:

  • Ваш код становится читаемым и самодокументируемым;
  • Вместо загадочных «магических чисел» вроде 0, 1, 2 появляются выразительные имена: DayOfWeek.MONDAY или TrafficLight.RED;
  • Компилятор будет ругаться, если вы попытаетесь присвоить некорректное значение;
  • За каждым элементом скрывается… обычное целое число! (Но к этому мы еще вернемся.)

Синтаксис объявления enum

// Общий шаблон объявления перечисления
public enum Имя
{
    КОНСТАНТА1 ,
    КОНСТАНТА2 ,
    КОНСТАНТА3
}
Синтаксис объявления перечисления enum

Объявить перечисление в 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) { ... } // Не надо!

Порядок элементов может измениться, и всё сломается. Используйте имена!

1
Задача
JAVA 25 SELF,  10 уровень,  4 лекция
Недоступна
Моделирование светофора 🚦
Моделирование светофора 🚦
1
Задача
JAVA 25 SELF,  10 уровень,  4 лекция
Недоступна
Сезонные поздравления в приложении 🌸☀️🍁❄️
Сезонные поздравления в приложении 🌸☀️🍁❄️
1
Задача
JAVA 25 SELF,  10 уровень,  4 лекция
Недоступна
Планирование недели в приложении 🗓️
Планирование недели в приложении 🗓️
1
Задача
JAVA 25 SELF,  10 уровень,  4 лекция
Недоступна
Навигация в космическом путешествии 🚀
Навигация в космическом путешествии 🚀
Комментарии (25)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Никита
Уровень 17
14 августа, 12:46
Помогите разобраться в чём дело?
Максим
Уровень 12
14 сентября, 17:11
ordinal нужно вывести у самой константы MARS в enum CelestialBody:
CelestialBody.MARS.ordinal()
Ian Astapov
Уровень 31
31 июля, 21:24
"Сообщения для SPRING и AUTUMN не отражают явно время года (жизнерадостные и соответствующие сезону). Рекомендую заменить текст для SPRING на более подходящий (например, "Весна — время цветения!") и для AUTUMN на позитивный, связанный с осенью (например, "Осень — время урожая!"). Также можно удалить ненужный default в switch, так как все значения перечисления покрыты." 😀😀😀 Impossible... Это так важно для кодинга? Нет слов
Ian Astapov
Уровень 31
31 июля, 21:19
"Заменить сообщения для SPRING и AUTUMN на русскоязычные уникальные жизнерадостные фразы, чтобы соответствовать требованию о выводе сообщений, соответствующих времени года и стилю примера." Really?!
grig_byQA Automation Engineer в ищу работу|есть что?
26 июня, 12:56
Во время тестирования, заметил что у enum есть метод .toString(). Выводит тоже значение что и .name(). Из общения с нейронкой: .name() - Нельзя переопределить – объявлен как final в классе Enum .toString() - Можно переопределить в своём enum, чтобы выводить более читаемый или локализованный текст. например, переопределение:
public String toString() {
      return "Зелёный";
};
то toString() вернул бы "Зелёный", а name() – "GREEN". еще заметил что .ordinal() для первого элемента вернет 1, а не 0.
Gusen14ka
Уровень 45
3 июля, 23:26
еще заметил что .ordinal() для первого элемента вернет 1, а не 0 Это не правда, решите, к примеру, задачу Навигация в космическом путешествии 🚀, чтобы убедиться, что ordinal начинает счёт с нуля (для марса, который по условию задачи 2ой в перечислении он выводит 1)
grig_byQA Automation Engineer в ищу работу|есть что?
4 июля, 22:06
точно, спасибо!
Anonymous #6483349
Уровень 29
15 апреля, 15:04
Как же мне нравится, что для решения задачи нужно вспомнить и применить знания полученные ранее.
C0N5P1RACY QA Automation Engineer
18 ноября 2025, 16:44
Что то я вообще не понял зачем нужен enum, из всех примеров что тут приводились, я понял только то, что он только усложняет код. В примере "Практика: используем enum в нашем приложении" я вообще не вижу смысла в использовании enum, это все можно сделать намного проще и удобнее, enum тут только делает код нечитаемым, так что мне тяжело понять зачем существует вообще enum
Popka
Уровень 24
25 декабря 2025, 18:37
Потому что ты пока мыслишь слишком узко в рамках одной маленькой программы. А когда у тебя 3000 классов, тебе проще будет написать в своем коде Week.MONDAY, чем прописывать String week1 = "Monday"; Плюс откуда ты знаешь что ты прав, и значение может быть именно таким. Вдруг ты работаешь в странной компании где неделя начинается со среды. ENUM нужен не для локальных задач, он нужен для удобной и безопасной архитектуры большого проекта в будущем. Когда у тебя 100 папок проще в одном файле сделать enum, чем во всех этих 100 папках прописывать каждый раз одно и то же
C0N5P1RACY QA Automation Engineer
25 декабря 2025, 18:57
Да дело в другом было, просто лекции в этом новом курсе написаны как то.. Ну не особо понятно в общем На классическом курсе пару дней назад проходил enum, и в сравнении с лекцией тут (в новом), там (в старом) более понятно написано, от чего усваивается намного проще
Yaroslav Yaroslav
Уровень 2
22 февраля, 13:08
Суть в том чтобы ограничит возможный набор аргументов. Допустим у тебя есть функция которая аргументом принимает строку и ты хочешь ограничить этот параметр определенным набором строк, вот тут тебе и пригодится Enum. Без него в твою функцию можно будет передать какую угодно строку. Пример:
enum OrderStatus {
    IN_PROGRESS, WAITING_PAYMENT, SUCCESS
}
Class Payment {
    public static void main(String[] args) {
        CreateOrder("WAITING_PAYMENT");
        CreateOrder("NOT_WAITING_PAYMENT"); //Компилятор выдаст ошибку
    }

   static void CreateOrder(String status) {
      System.out.println(OrderStatus.valueOf(status));
   }
}
Grrbrr7 System Engineer
3 ноября 2025, 06:10
Gans Electro
Уровень 59
7 июня, 13:31
😂
Grrbrr7 System Engineer
2 ноября 2025, 10:01
В пункте 4 лекции переменная russianName которая final названа не по фэнь шую
Ловкий Лев
Уровень 21
6 ноября 2025, 01:12
static final - константа и всегда именуется в UPPER_SNAKE_CASE Что касается просто final (не static) Если переменная: локальная, или поле экземпляра - как russianName в данном случае, то она обычно именуется как обычная переменная - в camelCase.
FDX
Уровень 47
10 октября 2025, 11:36
в задаче "сезонные поздравления" валидатор счел фразу "Lorem ipsum dolor sit amet" не достаточно праздничной и заставил переписать :D
Ksanders
Уровень 32
9 октября 2025, 15:57
Уже который раз в лекциях создаются объекты класса, но так ни разу не было вменяемого объяснения зачем эти объекты вообще нужны. Сюда еще и конструктор приплели, зачем? Новички только путаются. При этом чтобы получить базовое понятия о структуре класса, конструкторе и объектах - надо ждать уровня 14 😡