Перечисления (enum)

Что, если вы хотите в своей программе обеспечить использование только определённых значений для своего типа данных (т.е. вашего класса)? Например, только 7 специальных объектов класса DayOfWeek, соответствующих дням недели. Или только 12 специальных объектов класса Month, соответствующих месяцам. Самый удобный способ это сделать – использовать перечисления (enum).

Давайте познакомимся с такой полезной штукой, как перечисления в Java.

Смысл перечислений

Перечисления (enum) в Java – это специальный тип данных, который представляет из себя набор именованных констант (значений). Основная идея в том, чтобы создать тип данных, который может принимать только определённые значения. Это делает код гораздо более читаемым и безопасным. Сравните:

Единица – это ничто. Единица – это магическая константа. Чтобы понять, что означает единица, нужно приложить дополнительные усилия. Чтобы понять, что означает TUESDAY, усилий нужно гораздо меньше. То есть вы сберегаете свои программистские ресурсы на чтении кода, и направляете их на его разработку. В этом суть!

Кто-то может возразить, что можно использовать обычные переменные, объявленные как final, вместо перечислений. Например, где-нибудь в коде объявить final int TUESDAY = 1, и спокойно это использовать. Да, можно. И это уже будет лучше, чем писать просто единицу. Однако: применение enum-ов позволяет логично разбросать различные константы по сферам их применения, не смешивая всё в одном месте. В перечислении DayOfWeek хранятся дни недели, в перечислении UserRole хранятся роли пользователей. Всё на своих местах. Вдобавок, и DayOfWeek, и UserRole можно использовать в различных классах.

Более того, enum-ы обладают большими возможностями, чем обычные константы. Их сущности могут иметь свои поля и методы. Но давайте обо всём по порядку.

Как создать перечисление

Для создания перечисления используется ключевое слово enum. Давайте рассмотрим пример перечисления времён года. Их всего четыре. Не больше, не меньше: WINTER, SPRING, SUMMER и AUTUMN.

Согласно соглашению о кодировании, константы прописываются в верхнем регистре с нижними подчёркиваниями в качестве разделителей слов (uppercase). Так как сущности enum-ов – константы, то они именно в таком стиле и пишутся.

Теперь можно использовать эти значения из enum-а Season в других местах в коде. Например, в конструкции switch-case:

Поля и методы в enum

Что делает enum-ы гораздо более крутыми, чем обычные константы, так это возможность иметь собственные поля и методы, совсем как самые настоящие классы. Одна тонкость: конструктор enum-а всегда будет private и изменить это нельзя. Это логично – чтобы извне нельзя было создать неподходящую сущность (например, 8-ой день недели с названием “qwerty123”).

Добавим в созданный enum Season описание прямо внутри него. Оно будет храниться в приватном поле description. Публичным методом getDescription() его можно будет получить извне.

Протестируем:

Демонстрация вызова метода enum-а Season в консоль в IntelliJ IDEA

Результат именно такой, как и стоило ожидать. С помощью метода getDescription() в консоль было выведено описание поры года WINTER. И так будет со всеми сущностями enum-а Season. Конечно, хранить можно не только строки. А методы могут быть посложнее геттеров.

Занимательные факты про перечисления

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

В этом плане метод name() подходит больше, чем toString(), так как toString() впоследствии может быть переопределён разработчиком и возвращать какое-либо другое строковое представление, а не то название элемента, какое прописано непосредственно в коде.

Демонстрация вызова метода name() в enum Season в консоль в IntelliJ IDEA

Перечисления в Java могут наследоваться от интерфейсов:

При этом перечисления не могут наследоваться от классов!

На уровне внутренних механизмов, enum в Java являются особым типом класса. Каждый элемент перечисления является экземпляром этого класса. При этом перечисление неявно наследуется от класса Enum, который в свою очередь наследуется от класса Object. Таким образом, элементы перечисления унаследованы от Object. Посему можно использовать методы, определенные в Object, такие как toString(), equals() и hashCode().

Перечисления – это не какая-то экзотика, к которой прибегаешь чисто в целях изучения. Нет. Это удобная штука, которую лично я часто применяю на практике. Именуйте константы и будет вам счастье!

Добавить комментарий