До версии JDK5 явно недоставало перечислений — одного из языковых средств, потребность в котором остро ощущали многие программирующие нa Java.
В простейшей форме перечисление представляет собой список именованных констант. Несмотря на то что в Java имеются другие языковые средства с похожими функциональными возможностями, например завершенные переменные, многим программирующим нa Java все же не хватало принципиальной ясности перечислений, особенно потому, что они применяются во многих других языках программирования.
В версии JDК5 перечисления были внедрены в Java и наконец-то стали доступны для программирования на этом языке.
В простейшей форме перечисления в Java похожи на перечисления в других языках программирования, но это поверхностное сходство.
В языках вроде С++ перечисления просто являются списками целочисленных констант. А в Java перечисления определяют тип класса.
Благодаря тому что перечисления реализованы в виде классов, само понятие перечисления значительно расширяется.
Например, перечисления в Java могут иметь конструкторы, методы и переменные экземпляра. И несмотря на то что внедрения перечислений пришлось ждать несколько лет, реализация их в Java того стоила.
Перечисления создаются с помощью ключевого слова enum. В качестве примера ниже показано простое перечисление сортов яблок.
1 2 3 |
enum Apple { Jonathan, GoldenDel, RedDel, Winesap, Cortland } |
Идентификаторы Jonathan, GoldenDel и так далее называются коистаитами перечислимого типа. Каждая из них явно объявлена как открытый статический конечный член класса Apple.
Более того, они относятся к типу того перечисления, в котором объявлены (в данном случае — Apple ). В языке Java такие константы называются самотипизированными, причем префикс само относится к охватывающему их перечислению.
Объявив перечисление, можно создавать переменные данного типа. Но, несмотря на то, что перечисления определяют тип класса, получать экземпляры класса типа enum с помощью оператора new нельзя.
Вместо этого переменная перечисления объявляется и применяется практически так же, как и переменные примитивных типов.
В приведенном ниже примере объявляется переменная ар перечислимого типа Apple:
1 |
Apple ap; |
Переменная ар относится к типу Аррlе, и поэтому ей можно присвоить только те значения, которые определены в перечислении.
В следующем примере переменной ар присваивается значение RedDel:
1 |
ap = Apple.RedDel; |
Обратите внимание н а то, что значению RedDel предшествует тип Apple. Две константы перечислимого типа можно проверять на равенство с помощью операции отношения ==.
Например, в следующем условном операторе переменная ар сравнивается с константой Apple.GoldenDel:
1 |
if (ap == Apple.GoldenDel) // ... |
Значения перечислимого типа можно также использовать в упрамяющем операторе switch. Разумеется, для этого во всех выражениях ветвей case должны использоваться константы из того же самого перечисления, что и в самом операторе switch.
Например, следующий оператор switch составлен совершенно правильно:
1 2 3 4 5 6 7 8 |
// Использовать перечисление для управления оператором switch switch(ap) { case Jonathan: // ... case Winesap: // ... |
Обратите внимание на то, что в выражениях ветвей case имена констант указываются без уточнения имени их перечислимого типа, например Winesap, а не Apple.Winеsар.
Дело в том, что тип перечисления в операторе switсh уже неявно задает тип перечисления для выражений в ветвях case.
Следовательно, уточнять имена констант в выражениях ветвей case не нужно. В действительности любая попытка сделать это приведет к ошибке во время компиляции.
Когда выводится константа перечислимого типа, например, методом println(), то отображается ее имя. Например, в следующей строке кода:
1 |
System.out.println(Apple.Winesap) |
выводится имя Winesap.
Приведенный ниже пример программы подытоживает все сказанное выше, демонстрируя применение перечисления Apple.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
// Перечисление сортов яблок enum Apple { Jonathan, GoldenDel, RedDel, Winesap, Cortland } class EnumDemo { public static void main(String args[]) { Apple ap; ap = Apple.RedDel; // вывести значение перечислимого типа System.out.println("Значение ap: " + ap); System.out.println(); ap = Apple.GoldenDel; // сравнить два значения перечислимого типа if(ap == Apple.GoldenDel) { System.out.println("Переменная ap содержит GoldenDel.\n"); } // применить перечисление для управления оператором switch switch(ap) { case Jonathan: System.out.println("Сорт Jonathan красный."); break; case GoldenDel: System.out.println("Сорт Golden Delicious желтый."); break; case RedDel: System.out.println("Сорт Red Delicious красный."); break; case Winesap: System.out.println("Сорт Winesap красный."); break; case Cortland: System.out.println("Сорт Cortland красный."); break; } } } |
Эта программа выводит следующий результат:
1 2 3 4 5 |
Значение ap: RedDel Переменная ap содержит GoldenDel. Сорт Golden Delicious желтый. |