logo
Методичка Java

3.8.Типы-перечисления (enum)

Иногда требуется использовать элементы, которые не являются ни числами, ни строками, но ведут себя как имена элементов и одновременно обладают порядковыми номерами. Например, названия месяцев или дней недели. В этих случаях используют перечисления. Для задания типа какого-либо перечисления следует написать зарезервированное слово enum (сокращение от enumeration – “перечисление”), после которого имя задаваемого типа, а затем в фигурных скобках через запятую элементы перечисления. В качестве элементов можно использовать любые простые идентификаторы (не содержащие квалификаторов вида имя1.имя2).

Тип-перечисление обязан быть глобальным – он может задаваться либо на уровне пакета, либо в каком-либо классе. Но его нельзя задавать внутри какого-либо метода. Элементы перечисления могут иметь любые имена, в том числе совпадающие в разных перечислениях или совпадающие с именами классов или их членов – каждое перечисление имеет своё собственное пространство имён. Доступ к элементу перечисления осуществляется с квалификацией именем типа-перечисления:

ИмяТипа.имяЭлемента

У каждого элемента перечисления имеется порядковый номер, соответствующий его положению в наборе - нумерация начинается с нуля. Поэтому первый элемент имеет номер 0, второй элемент – номер 1, и так далее. Имеется функция ordinal(), возвращающая порядковый номер элемета в перечислении. Также имеется функция compareTo, позволяющая сравнивать два элемента перечисления - она возвращает разницу в их порядковых номерах.

Строковое представление значения можно получить с помощью функции name(). Преобразование из строки в значение типа “перечисление” осуществляется с помощью функции класса valueOf, в которую передаётся строковое представление значения.

Если требуется рассматривать элементы перечисления как массив, можно воспользоваться функцией values() – она возвращает массив элементов, к которым можно обращаться по индексу. Формат вызова функции такой: ИмяТипа.values()

Для примера зададим типы-перечисления Monthes (“месяцы”) и Spring (“весна”), соответствующие различным наборам месяцев:

enum Monthes {jan,feb,mar,apr,may,jun,jul,aug,sept,oct,nov,dec};

enum Spring { march, apr, may };

Названия месяцев мы намеренно пишем со строчной буквы для того, чтобы было понятно, что это идентификаторы переменных, а не типы. А имя марта написано по-разному в типах Monthes и Spring для того, чтобы показать независимость их пространств имён.

Объявление переменных типа “перечисление” делается так же, как для всех остальных типов, при этом переменные могут быть как неинициализированы, так и инициализированы при задании:

public Monthes m1 ,m2=Monthes.mar, m3;

- при задании в классе общедоступных полей m1, m2 и m3,

Spring spr1=Spring.apr, spr2;

- при задании в методе локальной переменной или задании в классе поля spr1 с пакетным уровнем доступа.

После чего возможны следующие операторы:

spr2=spr1;

spr1=Spring.may;

System.out.println("Результат сравнения="+spr2.compareTo(Spring.march));

После выполнения этих операторов в консольное окно будет выведен текст

Результат сравнения=1 ,

поскольку в переменной spr2 окажется значение Spring.apr , порядковый номер которого на 1 больше, чем у значения Spring.march , с которым идёт сравнение.

Пусть в переменной spr2 хранится значение Spring.may. Порядковый номер значения, хранящегося в переменной, можно получить с помощью вызова spr2.ordinal() . Он возвратит число 2, так как may – третий элемент перечисления (сдвиг на 1 получается из-за того, что нумерация начинается с нуля).

Строковое представление значения, хранящегося в переменной spr2, можно получить с помощью вызова spr2.name() . Он возвратит строку “may” - имя типа в возвращаемое значение не входит.

Если переменная типа “перечисление” не инициализирована, в ней хранится значение null. Поэтому вызов

System.out.println("spr2="+spr2);

осуществлённый до присваивания переменной spr2 значения возвратит строку

spr2=null

А вот попытки вызовов spr2.ordinal() или spr2.name() приведут к возникновению ошибки (исключительной ситуации) с диагностикой

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException

Получение значения типа Spring по номеру, хранящемуся в переменной i, осуществляется так:

spr1=Spring.values()[i];

Преобразование из строки в значение типа Spring будет выглядеть так:

spr1=Spring.valueOf("march");