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.