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

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

JAVA 25 SELF
10 уровень, 4 лекция
Открыта

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)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Никита Уровень 13
14 августа 2026
Помогите разобраться в чём дело?
Максим Уровень 11
14 сентября 2026
ordinal нужно вывести у самой константы MARS в enum CelestialBody:

CelestialBody.MARS.ordinal()
Ian Astapov Уровень 21
31 июля 2026
"Сообщения для SPRING и AUTUMN не отражают явно время года (жизнерадостные и соответствующие сезону). Рекомендую заменить текст для SPRING на более подходящий (например, "Весна — время цветения!") и для AUTUMN на позитивный, связанный с осенью (например, "Осень — время урожая!"). Также можно удалить ненужный default в switch, так как все значения перечисления покрыты." 😀😀😀 Impossible... Это так важно для кодинга? Нет слов
Ian Astapov Уровень 21
31 июля 2026
"Заменить сообщения для SPRING и AUTUMN на русскоязычные уникальные жизнерадостные фразы, чтобы соответствовать требованию о выводе сообщений, соответствующих времени года и стилю примера." Really?!
grig_by Уровень 21
26 июня 2026
Во время тестирования, заметил что у enum есть метод .toString(). Выводит тоже значение что и .name(). Из общения с нейронкой: .name() - Нельзя переопределить – объявлен как final в классе Enum .toString() - Можно переопределить в своём enum, чтобы выводить более читаемый или локализованный текст. например, переопределение:

public String toString() { 
      return "Зелёный"; 
}; 
то toString() вернул бы "Зелёный", а name() – "GREEN". еще заметил что .ordinal() для первого элемента вернет 1, а не 0.
Gusen14ka Уровень 2
3 июля 2026
еще заметил что .ordinal() для первого элемента вернет 1, а не 0 Это не правда, решите, к примеру, задачу Навигация в космическом путешествии 🚀, чтобы убедиться, что ordinal начинает счёт с нуля (для марса, который по условию задачи 2ой в перечислении он выводит 1)
grig_by Уровень 21
4 июля 2026
точно, спасибо!
Anonymous #6483349 Уровень 29
15 апреля 2026
Как же мне нравится, что для решения задачи нужно вспомнить и применить знания полученные ранее.
C0N5P1RACY Уровень 42
18 ноября 2025
Что то я вообще не понял зачем нужен enum, из всех примеров что тут приводились, я понял только то, что он только усложняет код. В примере "Практика: используем enum в нашем приложении" я вообще не вижу смысла в использовании enum, это все можно сделать намного проще и удобнее, enum тут только делает код нечитаемым, так что мне тяжело понять зачем существует вообще enum
Popka Уровень 1
25 декабря 2025
Потому что ты пока мыслишь слишком узко в рамках одной маленькой программы. А когда у тебя 3000 классов, тебе проще будет написать в своем коде Week.MONDAY, чем прописывать String week1 = "Monday"; Плюс откуда ты знаешь что ты прав, и значение может быть именно таким. Вдруг ты работаешь в странной компании где неделя начинается со среды. ENUM нужен не для локальных задач, он нужен для удобной и безопасной архитектуры большого проекта в будущем. Когда у тебя 100 папок проще в одном файле сделать enum, чем во всех этих 100 папках прописывать каждый раз одно и то же
C0N5P1RACY Уровень 42
25 декабря 2025
Да дело в другом было, просто лекции в этом новом курсе написаны как то.. Ну не особо понятно в общем На классическом курсе пару дней назад проходил enum, и в сравнении с лекцией тут (в новом), там (в старом) более понятно написано, от чего усваивается намного проще
Yaroslav Yaroslav Уровень 39
22 февраля 2026
Суть в том чтобы ограничит возможный набор аргументов. Допустим у тебя есть функция которая аргументом принимает строку и ты хочешь ограничить этот параметр определенным набором строк, вот тут тебе и пригодится 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 Уровень 46
3 ноября 2025
Gans Electro Уровень 42
7 июня 2026
😂
Grrbrr7 Уровень 46
2 ноября 2025
В пункте 4 лекции переменная russianName которая final названа не по фэнь шую
Ловкий Лев Уровень 21
6 ноября 2025
static final - константа и всегда именуется в UPPER_SNAKE_CASE Что касается просто final (не static) Если переменная: локальная, или поле экземпляра - как russianName в данном случае, то она обычно именуется как обычная переменная - в camelCase.
FDX Уровень 47
10 октября 2025
в задаче "сезонные поздравления" валидатор счел фразу "Lorem ipsum dolor sit amet" не достаточно праздничной и заставил переписать :D
Ksanders Уровень 32
9 октября 2025
Уже который раз в лекциях создаются объекты класса, но так ни разу не было вменяемого объяснения зачем эти объекты вообще нужны. Сюда еще и конструктор приплели, зачем? Новички только путаются. При этом чтобы получить базовое понятия о структуре класса, конструкторе и объектах - надо ждать уровня 14 😡