enum в Java

enum описывает закрытый набор именованных экземпляров. Каждая константа создаётся JVM один раз для данного загрузчика класса. Поэтому константы одного enum корректно сравнивать через ==.

enum Status {
    NEW(false),
    RUNNING(false),
    DONE(true),
    FAILED(true);
 
    private final boolean terminal;
 
    Status(boolean terminal) {
        this.terminal = terminal;
    }
 
    boolean isTerminal() {
        return terminal;
    }
}

Перечисление не просто список чисел: оно неявно наследует java.lang.Enum, может иметь поля, конструкторы и методы, а также реализовывать интерфейсы. Наследоваться от другого класса или enum нельзя.

Полезные операции

  • Status.valueOf("DONE") — точное имя или IllegalArgumentException;
  • status.name() — стабильное объявленное имя;
  • status.ordinal() — позиция; для хранения и протоколов использовать нельзя;
  • EnumSet<Status> — компактное множество;
  • EnumMap<Status, V> — эффективная карта по enum-ключам;
  • switch — проверяемая компилятором развилка по вариантам.
String label = switch (status) {
    case NEW -> "создана";
    case RUNNING -> "в работе";
    case DONE -> "готова";
    case FAILED -> "ошибка";
};

Ошибки проектирования

  • хранить ordinal() в БД: перестановка констант меняет смысл данных;
  • отдавать внутреннее имя наружу без явного контракта;
  • добавлять изменяемое состояние в singleton-константы;
  • молча использовать valueOf для пользовательского ввода без обработки ошибки.

Если набор вариантов должен расширяться плагинами во время выполнения, enum не подходит: он закрыт на этапе компиляции.

На собеседовании

Почему == подходит для enum? Для каждой константы существует единственный экземпляр в пределах загрузчика класса.

Можно ли создать enum через new? Нет; его конструкторы не вызываются пользовательским кодом.

Почему опасен ordinal()? Это деталь порядка объявления, а не устойчивый идентификатор.

Может ли enum реализовать интерфейс? Да, в том числе с разным поведением констант.

Связано: Классы Java, Базовый синтаксис java.