Перечисляемые типы (enum) в Java

Для объявления используется ключевое слово enum. Например, нам необходимо перечислить дни недели:

  public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }

Enum тип необходимо использовать, если нужно определить некоторое количество констант, значения которых известны заранее, например, варианты пунктов меню или планеты нашей солнечной системы. Следующая программа демонстрирует, как можно использовать, определенный выше набор дней недели.

  public class EnumTest { Day day; public EnumTest(Day day) { this.day = day; } public void tellItLikeItIs() { switch (day) { case MONDAY: System.out.println("Mondays are bad."); break; case FRIDAY: System.out.println("Fridays are better."); break; case SATURDAY: case SUNDAY: System.out.println("Weekends are best."); break; default: System.out.println("Midweek days are so-so."); break; } } public static void main(String[] args) { EnumTest firstDay = new EnumTest(Day.MONDAY); firstDay.tellItLikeItIs(); EnumTest thirdDay = new EnumTest(Day.WEDNESDAY); thirdDay.tellItLikeItIs(); EnumTest fifthDay = new EnumTest(Day.FRIDAY); fifthDay.tellItLikeItIs(); EnumTest sixthDay = new EnumTest(Day.SATURDAY); sixthDay.tellItLikeItIs(); EnumTest seventhDay = new EnumTest(Day.SUNDAY); seventhDay.tellItLikeItIs(); } }

Данная программа выведет:

  Mondays are bad. Midweek days are so-so. Fridays are better. Weekends are best. Weekends are best.

Перечисляемые типы в языке Java — более эффективный инструмент, чем аналоги в других языках. Объявление типа enum определяет класс (enum type), который может содержать методы и другие поля. Компилятор автоматически добавляет некоторые методы, когда создает тип enum. Например, он имеет статический метод values, который возвращает массив, содержащий значения объекта в порядке их объявления. Этот метод обычно используется в комбинации с конструкцией for-each для обхода всех значений типа enum. Например, следующий код обходит все планеты:

  for (Planet p: Planet.values()) { System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass)); }

В следующем примере, Planet — это перечисляемый тип, который содержит планеты солнечной системы. Они объявлены с их физическими свойствами: масса и радиус.

Константы объявлены вместе со значениями радиуса и массы. Эти значения передаются конструктору при создании константы. Синтаксис языка требует, чтобы константы объявлялись до остальных полей и методов, также после объявления необходима точка с зяпятой. Конструктор enum типа должен быть private или package-private, он автоматически создает перечисленные константы. Нельзя самостоятельно вызвать enum конструктор. В дополнение к конструктору и свойствам, Planet имеет методы для вычисления гравитации и веса объекта на каждой планете.

  public enum Planet { MERCURY (3.303e+23, 2.4397e6), VENUS (4.869e+24, 6.0518e6), EARTH (5.976e+24, 6.37814e6), MARS (6.421e+23, 3.3972e6), JUPITER (1.9e+27, 7.1492e7), SATURN (5.688e+26, 6.0268e7), URANUS (8.686e+25, 2.5559e7), NEPTUNE (1.024e+26, 2.4746e7); private final double mass; // в килограммах private final double radius; // в метрах Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } private double mass() { return mass; } private double radius() { return radius; } // гравитационная постоянная public static final double G = 6.67300E-11; double surfaceGravity() { return G * mass / (radius * radius); } double surfaceWeight(double otherMass) { return otherMass * surfaceGravity(); } public static void main(String[] args) { if (args.length!= 1) { System.err.println("Usage: java Planet <earth_weight>"); System.exit(-1); } double earthWeight = Double.parseDouble(args[0]); double mass = earthWeight/EARTH.surfaceGravity(); for (Planet p: Planet.values()) System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass)); } }

Если запустить Planet.class из командной строки с параметром 175, то программа выведет:

  $ java Planet 175 Your weight on MERCURY is 66.107583 Your weight on VENUS is 158.374842 Your weight on EARTH is 175.000000 Your weight on MARS is 66.279007 Your weight on JUPITER is 442.847567 Your weight on SATURN is 186.552719 Your weight on URANUS is 158.397260 Your weight on NEPTUNE is 199.207413

Visual Basic

Перечисляемые типы обычно используются для определения набора именованных целочисленных констант. При определении перечисляемого типа используется пара ключевых слов Enum-End Enum вместе с модификатором доступа. Перечисляемый тип может содержать только целочисленные типы вроде Integer или Long (тип Char недопустим). Например, в следующем фрагменте определяется открытый перечисляемый тип с именем BonusStructure:

Public Enum BonusStructureNone = 0FirstLevel = 1SecondLevel = 2End Enum

После этого в любом месте программы можно объявить переменную типа BonusStructure:

Dim bonusLevel As BonusStructure

При работе с перечисляемыми типами, как и с другими структурными типами, ключевое слово New не используется.

Примечание
Если в перечисляемом типе указаны только имена без числовых значений,.
NET начинает отсчет с 0 и увеличивает значение на 1 для каждой новой константы. Если задано только первое число, то каждое следующее значение вычисляется увеличением предыдущего на 1.

Определив в проекте перечисляемый тип, вы можете использовать конструкции вида:

Bonus =Tom.Sales * bonusLevel.SecondLevel

Поскольку перечисляемые типы неявно интерпретируются как общие, в ссылках на них можно указывать имя перечисляемого типа вместо имени переменной:

Public Function Calcu1ateBonus(ByVal theSales As Decimal) As DecimalReturn theSales * BonusStructure.SecondLevelEnd Function

Одним из традиционных недостатков перечисляемых типов было отсутствие удобных средств для получения имени по значению, что затрудняло отладку программ. В классе Enum, базовом для всех перечисляемых типов, определены очень полезные методы для получения подобной информации. Например, следующая команда возвращает строку FirstLevel:

BonusStructure.GetName(bonusLevel.GetType.l)

Данный фрагмент выводит все имена, входящие в перечисляемый тип:

Dim enumNames As String().s As StringenumNames = BonusStructure.GetNames(bonusLevel.GetType)For Eachs In enumNamesSystem.Console.WriteLine(s) Next

Критика

Тип перечисление является традиционным для развитых языков программирования, используется достаточно широко и часто воспринимается как нечто само собой разумеющееся. Тем не менее, этот тип также не обходится без критики со стороны теоретиков и практиков программирования. Так, при разработке языка программирования Оберон перечислимые типы попали в список возможностей, которые были удалены из языка. Никлаус Вирт, разработчик языка, назвал следующие причины:

· «во всё возрастающем числе программ непродуманное использование перечислений … приводит к демографическому взрыву среди типов, что, в свою очередь, ведёт не к ясности программ, а к многословию»[1];

· когда тип перечисление экспортируется модулем (то есть становится частью интерфейса) нарушается общее правило — команда экспорта типа экспортирует одновременно все его элементы, тогда как для всех остальных типов экспорт типа скрывает его внутреннюю структуру;

· с точки зрения обеспечения удобочитаемости программ ничто не мешает вместо перечислимого типа использовать просто группу совместно определённых именованных констант, особенно при наличии таких языковых механизмов, как модули или классы.

С другой стороны, например, в Java, первоначально не содержащей перечислимого типа, этот тип был впоследствии введён из соображений не только удобства, но и надёжности: проблема использования вместо перечислений групп именованных констант в том, что отсутствует контроль со стороны компилятора как за уникальностью значений констант, так и за возможностью случайного присваивания переменным значений, не соответствующих ни одной из этих констант.

C++

Перечисления в языке C++ прямо наследуют поведение перечислений языка C, за исключением того, что перечисляемый тип в C++ — настоящий тип, и ключевое слово enumиспользуется только при объявлении такого типа. Если при обработке параметра являющегося перечислением, какое-либо значение из перечисления не обрабатывается (например один из элементов перечисления забыли обработать в конструкции switch), то компилятор может выдать предупреждение о забытом значении.[2]

C#

enum Cardsuit { Clubs, Diamonds, Spades, Hearts }; ] Java

В первоначальной Java перечислений не было, вместо них предлагалось использовать классы со статическими константами. Начиная с версии 5 (1.5) перечисления были введены в язык, они представляют собой полноценный класс, в который можно добавлять произвольное количество полей и методов. Перечисления были введены для улучшенного контроля за типобезопасностью.[3]

enum Cardsuit { Clubs, Diamonds, Spades, Hearts }

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: