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 для типа ДеньНедели:
| Код | Примечание |
|---|---|
|
Новый тип DayПонедельник Вторник Среда Четверг Пятница Суббота Воскресенье |
Присваивать значения переменным этого типа можно таким образом:
Day day = Day.MONDAY;
Пример:
| Код | Примечание |
|---|---|
|
На экран будет выведено: |
3. Методы enum’а
Тип enum имеет несколько встроенных методов, два из них очень интересные:
Статический метод values() возвращает массив всех значений типа enum:
| Код | Примечание |
|---|---|
|
В переменную days сохраняется массив значений типа Day (7 штук)Выводим содержимое массива на экран: |
Метод ordinal() возвращает порядковый номер константы. Вызывать его нужно не у класса enum, а у значения enum:
| Код | Вывод на экран |
|---|---|
|
|
4. Преобразование в класс
На самом деле никакой магии тут нет, и компилятор просто подсыпал нам немного синтаксического сахара. Во время компиляции класс enum Day будет преобразован в обычный класс:
| Код, упрощенная версия | Примечание |
|---|---|
|
Класс DayСписок статических констант-значений Массив со всеми значениями типа DayПеременная со значением конкретного объекта Dayprivate конструктор класса Day — объекты класса Day можно создавать только внутри класса Day.Метод ordinal нужно вызвать у объекта Day.Он возвращает значение объекта — value.Метод возвращает статический массив со всеми значениями класса Day |
Если убрать из класса Day все статические методы и переменные, мы получим такую картину:
| Код | Примечание |
|---|---|
|
Переменная 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];
Примеры:
| Код | Примечание |
|---|---|
|
Понедельник Получаем индекс понедельника (0) День недели на 2 дня позже понедельника |
Важный момент, т.к. значения типа enum представляют собой фиксированный набор констант, их можно сравнивать через ==. Ну не может существовать двух одинаковых объектов MONDAY с разными ссылками. Каждый объект-значение типа enum существует только в единственном экземпляре. Поэтому сравнение переменных типа enum через == всегда будет работать.
6. Добавление своих методов в enum
Так как enum во время компиляции превращается в обычный класс, в нем можно объявлять методы: эти методы просто добавятся в класс, который сгенерирует компилятор. Например, мы хотим, чтобы наш enum Day возвращал не массив значений, а список.
Тогда в него можно дописать такой код:
| Код | Примечание |
|---|---|
|
После списка значений нужно поставить точку с запятой. Создаем объект ArrayList.Добавляем в него значения из массива: его возвращает метод values().Возвращаем список. |
Теперь этот метод можно вызывать в коде:
| Код | Примечание |
|---|---|
|
В переменную list будет сохранен список всех значений enum’а Day. |
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ