JavaRush/Курсы/Java Syntax Pro/Новый тип данных – enum: перечисление

Новый тип данных – enum: перечисление

Открыта

1. Предыстория появления enum

Сегодня мы изучим еще одну разновидность типов данных в Java — enum. Название enum происходит от слова Enumeration — перечисление. Что же это за тип данных и с чем его едят?

Иногда в работе программиста возникает необходимость создать новый тип данных, переменные которого принимают только значения из небольшого фиксированного списка.

Например, тип ДеньНедели может принимать только значения ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, ... Всего 7 значений. Или тип Месяц может принимать только значения ЯНВАРЬ, ФЕВРАЛЬ, МАРТ, ... Всего 12 значений.

Можно, конечно, использовать числа (тип int): 1 — понедельник, 2 — вторник и т.д. Но кто-то случайно может присвоить такой переменной значение 8, или, например, значение 0.

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

Поэтому в Java придумали тип данных, который состоит из конечного набора значений — enum.


2. Объявление типа

Выглядит объявление нового enum типа данных так:

enum ИмяТипа
{
   ЗНАЧЕНИЕ1,
   ЗНАЧЕНИЕ2,
   ЗНАЧЕНИЕ3
}

Где ИмяТипа — это имя нового типа (класса), а в скобках через запятую перечислены возможные значения: Значение1, Значение2, Значение3.

Давайте ради примера создадим свой enum для типа ДеньНедели:

Код Примечание
enum Day
{
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY,
   SUNDAY
}
Новый тип Day

Понедельник
Вторник
Среда
Четверг
Пятница
Суббота
Воскресенье

Присваивать значения переменным этого типа можно таким образом:

Day day = Day.MONDAY;

Пример:

Код Примечание
Day day = Day.FRIDAY;
System.out.println(day);
На экран будет выведено:
FRIDAY


3. Методы enum’а

Тип enum имеет несколько встроенных методов, два из них очень интересные:

Статический метод values() возвращает массив всех значений типа enum:

Код Примечание
Day[] days = Day.values();

for (Day day: days)
   System.out.println(day);







System.out.println(days[2]);
В переменную days сохраняется массив значений типа Day (7 штук)

Выводим содержимое массива на экран:
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY

WEDNESDAY

Метод ordinal() возвращает порядковый номер константы. Вызывать его нужно не у класса enum, а у значения enum:

Код Вывод на экран
System.out.println(Day.MONDAY.ordinal());
System.out.println(Day.FRIDAY.ordinal());
System.out.println(Day.SUNDAY.ordinal());
0
4
6


4. Преобразование в класс

На самом деле никакой магии тут нет, и компилятор просто подсыпал нам немного синтаксического сахара. Во время компиляции класс enum Day будет преобразован в обычный класс:

Код, упрощенная версия Примечание
public class Day
{
   public static final Day MONDAY = new Day(0);
   public static final Day TUESDAY = new Day(1);
   public static final Day WEDNESDAY = new Day(2);
   public static final Day THURSDAY = new Day(3);
   public static final Day FRIDAY = new Day(4);
   public static final Day SATURDAY = new Day(5);
   public static final Day SUNDAY = new Day(6);

    private static final Day[] array = {MONDAY, TUESDAY,
      WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};

   private final int value;

   private Day (int value)
   {
      this.value = value;
   }

   public int ordinal()
   {
      return this.value;
   }

   public static Day[] values()
   {
      return array;
   }
}
Класс Day

Список статических констант-значений







Массив со всеми значениями типа Day


Переменная со значением конкретного объекта Day

private конструктор класса Day — объекты класса Day можно создавать только внутри класса Day.



Метод ordinal нужно вызвать у объекта Day.

Он возвращает значение объекта — value.


Метод возвращает статический массив со всеми значениями класса Day

Если убрать из класса Day все статические методы и переменные, мы получим такую картину:

Код Примечание
public class Day
{
  private int value;

  private Day (int value)
  {
    this.value = value;
  }

  public int ordinal()
  {
    return this.value;
  }
}


Переменная value хранит значение объекта Day

Объекты Day можно создавать только внутри класса Day — конструктор private.




Метод ordinal() возвращает значение value объекта Day.

Т.е. в принципе ничего страшного тут не происходит. Компилятор создает класс Day, затем добавляет в него константы, которые были значениями у enum, добавляет недостающие методы и делает конструктор класса private. Как работают конструкторы, мы разберем немного позднее.

Теперь, думаем, понятно, почему мы заносим значение в переменную таким образом:

Day day = Day.MONDAY;

MONDAY — это просто статическое поле (константа) класса Day. А при обращении к статическим методам и полям извне класса перед именем поля или метода нужно указывать имя класса.



5. Еще методы enum’а

Еще у всех enum-классов есть несколько интересных особенностей.

Преобразование в строку и обратно

Чтобы преобразовать объект типа enum в строку, у него нужно вызвать метод toString().

String str = Day.MONDAY.toString();

Для обратного преобразования (строки в объект Day) можно воспользоваться статическим методом valueOf():

Day day = Day.valueOf("MONDAY");

Очень удобно и полезно во многих случаях.

Преобразование в число и обратно

Как преобразовать объект типа enum в число, вы уже знаете: для этого нужно вызвать метод ordinal():

int index = Day.MONDAY.ordinal();

Для обратного преобразования (числа в объект Day) нужно воспользоваться конструкцией подлиннее:

Day day = Day.values()[2];

Примеры:

Код Примечание
Day day = Day.MONDAY;
int index = day.ordinal();
Day newDay = Day.values()[index+2];
Понедельник
Получаем индекс понедельника (0)
День недели на 2 дня позже понедельника

Важный момент, т.к. значения типа enum представляют собой фиксированный набор констант, их можно сравнивать через ==. Ну не может существовать двух одинаковых объектов MONDAY с разными ссылками. Каждый объект-значение типа enum существует только в единственном экземпляре. Поэтому сравнение переменных типа enum через == всегда будет работать.



6. Добавление своих методов в enum

Так как enum во время компиляции превращается в обычный класс, в нем можно объявлять методы: эти методы просто добавятся в класс, который сгенерирует компилятор. Например, мы хотим, чтобы наш enum Day возвращал не массив значений, а список.

Тогда в него можно дописать такой код:

Код Примечание
enum Day
{
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY,
   SUNDAY;

   public static List<Day> asList()
   {
      ArrayList<Day> list = new ArrayList<Day>();

      Collections.addAll(list, values());

      return list;
   }

}








После списка значений нужно поставить точку с запятой.



Создаем объект ArrayList.

Добавляем в него значения из массива: его возвращает метод values().
Возвращаем список.

Теперь этот метод можно вызывать в коде:

Код Примечание
List<Day> list = Day.asList();
В переменную list будет сохранен список всех значений enum’а Day.
Комментарии (250)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Евгений
Уровень 16
19 марта, 20:00
Вроде когда проходили про static всё было понятно, а когда начал делать задачу Трансформируем enum в класс поплыл вообще (((
Grigoryvvv
Уровень 28
Expert
22 февраля, 20:07
25.02.2026 / 14 уровень ● Явный вызов метода toString() у любых объектов: Чтобы преобразовать объект в строку, у него нужно вызвать метод toString():
String str = Day.MONDAY.toString();
При обычном присваивании объекта строке, нам нужно делать это явно, указывая вручную метод toString() у нашего объекта. Метод toString() наследуется от главного класса Object и есть у всех создаваемых объектов любых классов. У класса Day метод toString() переопределен и возвращает имя константы. Если представить упрощено (как будто у нас один день недели):
public class Day {
    public static final Day MONDAY = new Day(0);

    @Override
    public String toString() {
        return "MONDAY";
    }
}
● Неявный вызов метода toString() у любых объектов: В других случаях, всякий раз, когда когда объект нужно превратить в текст (String), производиться неявный вызов метода toString() без нашего участия : • При выводе в консоль Это как раз пример из лекции
Day day = Day.MONDAY;     /* в поле day хранится только ссылка на объект MONDAY */
System.out.println(day); /* строка обрабатывается как
System.out.println(day.toString()); */
происходит неявный вызов метода toString() для объекта, в консоль выводится "MONDAY". • При конкатенации со строкой
Day day = Day.MONDAY;
String text = "Сегодня: " + day;  /* строка обрабатывается как
String text = "Сегодня: " + day.toString(); */
при склеивании строк происходит неявный вызов метода toString() для объекта, в консоль выводится "Сегодня: MONDAY" • При логировании
Day day = Day.MONDAY;
logger.info("Day: {}", day);  /* строка обрабатывается как
logger.info("Day: {}", day.toString()); */
Никита
Уровень 1
24 июля 2025, 14:18
Пример реализации калькулятора через enum:
public enum Operation {
    PLUS { double eval(double x, double y){ return x + y; } },
    MINUS { double eval(double x, double y) { return x - y;} },
    TIMES { double eval(double x, double y) { return x * y;} },
    DIVIDE { double eval(double x, double y) { return x / y;} };

    abstract double eval(double x, double y);

    public static void main(String[] args) {
        double x = -23.567, y = 0.236;
        for (Operation op: Operation.values()) {
            System.out.println(op.eval(x, y));
        }
    }
}
Anonymous #3585174
Уровень 33
6 июля 2025, 13:27
Like
theUncleFyodor DevSecOps
27 мая 2025, 14:08
чертов валидатор... Применяешь все полученные знания, пишешь красивый код - не принято (убедитесь, что используете переменную Seasons) Смотришь правильный ответ - 4 подряд println... 🤮🤮🤮
FosTeR
Уровень 51
18 декабря 2025, 17:44
У меня через цикл(форИч) принял😎
Валерий
Уровень 48
30 апреля 2025, 06:59
Как лектор, мне Андрей больше всего нравится. Очень хорошо рассказывает
MaestroVLG QA Engineer
6 мая 2025, 13:11
Здесь есть лекторы?
Валерий
Уровень 48
9 мая 2025, 19:53
Если подписка на университет, то на страничку добавляются лекции в видеоформате
17 апреля 2025, 15:33
public static Month[] getWinterMonths() {
       return new Month[]{DECEMBER, JANUARY, FEBRUARY};
}
Danya Java Developer
16 апреля 2025, 21:46
немного не понял предпоследнюю задачу
VictorThe main expert in Automa в Строительная компани
27 января 2025, 20:22
Вот такой вывод на консоль для пятой задачи "Месяцы в сезоне", а то смотреть не интересно - ничего не происходит: public class Solution { public static void main(String[] args) { Month[] p1 = Month.getWinterMonths(); Month[] p2 = Month.getSpringMonths(); Month[] p3 = Month.getSummerMonths(); Month[] p4 = Month.getAutumnMonths(); System.out.println(Arrays.asList(p1)); System.out.println(Arrays.asList(p2)); System.out.println(Arrays.asList(p3)); System.out.println(Arrays.asList(p4)); } }
Ilya Klimchev Backend Developer
24 октября 2024, 12:14
Если всё так, если Enum'ы - это действительно всего лишь синтаксический сахар, то автору низкий поклон
6 июля, 19:10
тебе нужны гарантии?