Elettracompany.com

Компьютерный справочник
1 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Enum class java

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

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

Перечисления создаются с использованием ключевого слова enum. Создадим перечисление семейства кошачьих:

Идентификаторы в фигурных скобках называются константами перечисления. Каждый из них явно объявлен как открытый статический финальный член класса Cat. Объявив перечисление, вы можете создавать переменные этого типа. Но делать это нужно без оператора new, а в упрощенном виде. Объявим переменную manul перечислимого типа Cat.

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

Обратите внимание, что во время присваивания вы указываете и тип Cat.

Использование перечисляемых переменных позволят избежать ошибок. Например, мы хотим использовать только числа 1, 2, 3 и такой способ не позволит использовать числа 0, 5, 9 и т.д.

Перечислимые константы можно проверить на равенство:

Также их можно применять в конструкции switch, где у операторов case используются константы из перечисления enum. При этом имена констант используются без имени типа перечисления.

Метод values()

Автоматически предопределённый метод для перечисления values() возвращает массив, содержащий список констант перечисления.

Для примера использовалась дополнительная переменная allcats, которой присваивается ссылка на массив перечислимых значений. Можно обойтись без дополнительной переменной.

Метод valueOf(String string)

Автоматически предопределённый метод для перечисления valueOf() возвращает константу перечисления, значение которой соответствует строке, переданной в параметре.

Так как перечисление в Java — это тип класса, то вы можете использовать конструкторы, добавлять переменных экземпляров, методы и интерфейсы. Следует сказать, что в Android сначала не рекомендовалось использовать перечисления из-за большого потребления памяти. Сейчас вроде это ограничение сняли, но тем не менее пока перечисления не так широко используются в приложениях для мобильных устройств, поэтому подробно разбирать все возможности перечисления не будем.

Метод ordinal()

У перечислений есть несколько удобных методов. Например, вы можете получить значение, которое указывает позицию константы в списке констант перечисления (порядковое значение или ordinal value), с помощью метода ordinal(). Порядковые значения начинаются с нуля.

Методы compareTo() и equals()

Также можно сравнивать порядковые значения констант одного и того же перечисления с помощью метода compareTo(). Или сравнить на эквивалентность через метод equals().

Увлекаться не стоит из-за большого потребления памяти. Сравним.

По этой причине на сегодняшний день в Android рекомендуется избегать enum. Хотя в последнее время я встречал использование перечислений в исходных кодах Android.

Enum в java

Сегодня мы попробуем разобрать такое понятие как enum в языке java. Проще говоря — перечисления. Ведь очень часто во время написания программ нам необходимо использовать глобальные константы или только допустимые значения некоторого типа данных. Для этих целей идеально подойдет enum.

Давайте разберем все по порядку и закрепим теорию примерами.

Enum (перечисления) — это по сути обычный класс. Он может иметь конструкторы, методы и переменные. Для того, чтобы класс стал перечислением нужно пометить его ключевым словом enum.

Но, если бы все было так просто данный тип не отделяли бы от простого класса и не выносили бы перечисления как отдельный вид.

После объявления данного класса-перечисления можно начать добавлять переменные. Для наглядного примера я создам вполне реальную задачу, которая могла бы случиться на серьезных проектах. Допустим у нас есть сайт. Его посещают — пользователи. У пользователей разные роли на сайте. Кто-то может быть администратором, кто-то просто пользователем или модератором. Давайте реализуем простой доступ к функционалу в зависимости от роли.

Как видно из примера выше — мы успешно использовали перечисления для реализации ролей пользователя. Обратите внимание на сравнение строки с enum. Для того, чтобы сравнить фактическое значение перечисления нужно вызвать встроенный метод name() или toString(). Об этой особенности очень важно знать. Для закрепления вот Вам пример:

Результатом выполнения кода будет:

Строка System.out.println(UserRole.USER); выведет в консоль USER, но во время сравнения строки USER со строкой UserRole.USER будет false. Об этой особенности забывают даже опытные программисты.

Читать еще:  Java development kit mac

Как уже было сказано выше — перечисления могут иметь конструкторы и методы. Давайте на примере разберем их использование. Ведь, иногда возникают ситуации, когда в enum нужно хранить что-то больше, чем просто строку.

Пример выше это часть реального перечисления, которое я создал когда писал приложение Онлайн тесты. Было очень удобно хранить ошибку в enum. Я могу использовать одну переменную в нескольких частях моего кода. И, когда мне было необходимо изменить значение ошибки — мне было достаточно отредактировать только значение перечисления.

Как по мне, такой enum использовать очень удобно и просто.

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

Перечисления в Java (Java Enum)

Перечисления (Enum) были введены в Java начиная с версии 1.5 с целью улучшения контроля за типобезопасностью (невозможно назначить переменной значение извне заданного множества допустимых значений). До этого для реализации перечислений предлагалось использовать классы со статическими константами.

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

В результате на консоль будет выведено Черви . Стоит отметить, что перечисления не нужно сравнивать через equals, достаточно сравнения по ссылке.

Одной из наиболее ценной возможностью применения перечислений в Java является использование его внутри оператора switch:

В Java, в отличие от большинства других языков программирования, перечисления представляют собой полноценный класс, наследуемый от java.lang.Enum (наследование автоматически выполняет компилятор Java), в который можно добавлять произвольное количество конструкторов, полей и методов.

java.lang.Enum содержит ряд полезных методов:

  • public final String name() – возвращает задекларированное имя константы.
  • public String toString() – по умолчанию возвращает задекларированное имя константы, однако в отличие от name() может быть переопределен.
  • public final int ordinal() – порядковый номер в котором экземпляр перечисления обозначен внутри enum.
  • public final int compareTo(E o) — имитирует порядок, предоставляемый методом ordinal(). Т.О. enumограничивает сравнения только порядком их объявления.

Так же есть два метода не определенные в классе java.lang.Enum, а добавляемые в процессе компиляции:

  • public static EnumClass valueOf(String name) – возвращает элемент перечисления EnumClassс названием, равным name. В случае если элемент не будет найден, будет выброшен IllegalArgumentExceptionили NullPointerExceptionесли аргумент будет null.
  • public static EnumClass[] values() – возвращает список всех элементов enum-класса.

Важным моментом является факт того, что невозможно создавать экземпляры перечисления вне границ Enum, поскольку у него нет public конструктора, и компилятор не допускает наличие public конструкторов внутри Enum. Экземпляры должны создаваться внутри самого Enum.

Примечание: экземпляр перечисления создается в момент первого обращения к ней.

Пример, охватывающий все вышесказанное:
Результат выполнения:
Наследование и полиморфизм в enum

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

Например, можно реализовать набор оконных функций для преобразования Фурье (из реального проекта):

Enum в java может реализовывать интефейс, что собственно он уже и делает по умолчанию, реализуя интерфейс Comparable . И именно поэтому Enum по умолчанию может использоваться в упорядоченных коллекциях (например, TreeSet или TreeMap).

Наследовать класс Enum не может, т.к. уже наследуется от java.lang.Enum, а множественного наследования классов в Java нет.

В дополнение стоит указать на наличие в Java Collections API специальных классов EnumSet и EnumMap которые производительнее чем HashSet и HashMap при использовании enum в качестве ключей. По причине того, что если enum содержит не более 64 различных значений, то EnumSet хранит всё в одном поле типа long в битовой маске. А EnumMap хранит все значения в обычном массиве той же длины, сколько элементов в enum (при этом его длинна никогда не изменяется), а ключи не хранит вовсе. Так как у каждого значения в enum есть порядковый номер, получаемый при помощи ordinal().

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

При программировании часто необходимо использовать ограниченное множество допустимых значений для некоторого типа данных. Так, например, день недели может иметь 7 разных значений, месяцев в году не более 12, и всего 4 времени года. Для решения подобных задач во многих языках программирования предусмотрен специальный тип данных — перечисление (enum). В Java перечисление enum появилось не сразу только в версии Java 5.

Читать еще:  Ошибка кс го d3dx9 43 dll

Синтаксис перечисления enum

Описание с помощью enum типа данных Season для хранения времени года можно представить в следующем виде :

Простой пример использования enum :

В результате выполнения данного кода в консоль будет выведен текст SPRING.

Перечисление enum — это класс

При объявлении переменной типа enum неявно создается класс производный от java.lang.Enum. Условно рассматриваемая конструкция enum Season < . >эквивалентна class Season extends java.lang.Enum < . >. Явным образом наследоваться от java.lang.Enum не позволяет компилятор. Но то, что enum наследуется, легко убедиться с помощью reflection:

В консоль будет выведено :

Таким образом наследование за разработчика автоматически выполняет компилятор Java. Далее в тексте enum-классом будет называться класс, созданный компилятором для реализации перечисления, а возможные значения перечисляемого типа — элементами enum’a.

Элементы перечисления enum

Элементы enum Season (WINTER, SPRING и т.д.) — это статически доступные экземпляры enum-класса Season. Их статическая доступность позволяет выполнять сравнение с помощью оператора сравнения ссылок ==. Например :

Название и порядковый номер элемента enum

Пример использования методов enum для извлечения информации об объекте :

В консоле будет представлено:

В примере использованы методы name(), toString() и ordinal(). Семантика методов — очевидна. Следует обратить внимание, что данные методы enum-класс наследует от класса java.lang.Enum

Получение елемента enum по строковому представлению его имени

Довольно часто возникает задача необходимости получения элемента enum по его строковому представлению. Для этих целей в каждом enum-классе компилятор автоматически создает специальный статический метод : public static EnumClass valueOf (String name), который возвращает элемент перечисления EnumClass с названием, равным name. Например:

В результате выполнения кода переменная season будет равна Season.WINTER.
Cледует обратить внимание, что если элемент не будет найден, то будет вызвано исключение IllegalArgumentException, а в случае, если name=nullNullPointerException. Об этом не следует забывать.

Получение элементов перечисления

Если необходимо получить список всех элементов enum-класса во время выполнения, то для этих целей в следует использовать метод: public static EnumClass[] values(). Например:

В консоль будет выведено:

Необходимо иметь в виду, что ни метод valueOf(), ни метод values() не определены в классе java.lang.Enum. Они автоматически добавляются на этапе компиляции enum-класса.

Добавление методов в enum-класс

Можно добавлять собственные методы как в enum-класс, так и в его элементы:

Тот же пример, но с полиморфизмом:

Наследование в enum

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

Здесь объявляется перечисление Type с тремя элементами INT, INTEGER и STRING. Компилятор создаст следующие классы и объекты:

  • Type — класс производный от java.lang.Enum
  • INT — объект 1-го класса производного от Type
  • INTEGER — объект 2-го класса производного от Type
  • STRING — объект 3-го класса производного от Type

Три производных класса будут созданы с полиморфным методом Object parse (String) и конструктором Type (. boolean). При этом объекты классов INT, INTEGER и STRING существуют в единственном экземпляре и доступны статически. В этом можно убедиться, выполнив следующий код :

Результат выполнения кода :

Таким образом, компилятор создал класс Type и 3 nested класса, производных от Type.

Декомпилированный enum-class с наследованием

В подтверждение вышесказанному можно привести результат декомпиляции перечисления Type из примера выше:

Перечисления и параметрический полиморфизм

Может возникнуть вопрос: «А почему вышеуказанное перечисление Type не использует generics» ? Причина кроется в том, что в Java использование generics в enum запрещено. Так следующий пример не будет скомпилирован:

Java.lang.Enum Class в Java

Класс enum присутствует в пакете java.lang. Это общий базовый класс всех типов перечисления языка Java. Для получения информации о перечисления, обратитесь enum в Java

Читать еще:  Java возведение в степень int

Декларация класса

Как видим, этот Enum является абстрактным классом, поэтому мы не можем создать объект класса Enum.

Методы в классе Enum

Класс Enum предоставляет 10 полезных методов. Большинство из них переопределены из класса Object . Эти методы объявлены как окончательные в классе Enum, поэтому программист не может изменить ни одну из констант enum.

    final String name () : этот метод возвращает имя этой константы перечисления, которое в точности соответствует объявлению в объявлении перечисления.

// Java-программа для демонстрации метода name ()

public class Test

public static void main(String[] args)

Color c1 = Color.RED;

System.out.print( «Name of enum constant: » );

final int ordinal () : этот метод возвращает индекс этой константы перечисления.

// Java-программа для демонстрации метода ordinal ()

public class Test

public static void main(String[] args)

Color c1 = Color.GREEN;

System.out.print( «ordinal of enum constant » +c1.name()+ » : » );

String toString () : этот метод возвращает объект String, представляющий эту константу перечисления. Этот метод такой же, как метод name ().

// Java-программа для демонстрации метода toString ()

public class Test

public static void main(String[] args)

Color c1 = Color.GREEN;

// получаем строковое представление enum

// используя метод toString ()

String str = c1.toString();

final boolean equals (Object obj) : этот метод возвращает true, если указанный объект равен этой константе enum, в противном случае возвращает false.

// Java-программа для демонстрации метода equals ()

public class Test

public static void main(String[] args)

Color c1 = Color.RED;

Color c2 = Color.GREEN;

Color c3 = Color.RED;

// проверка равенства между перечислениями

// используя метод equals ()

boolean b1 = c1.equals(c2);

boolean b2 = c1.equals(c3);

boolean b3 = c2.equals( null );

System.out.println( «is c1 equal to c2 : » + b1);

System.out.println( «is c1 equal to c3 : » + b2);

System.out.println( «is c2 equal to null : » + b3);

final int hashCode () : этот метод возвращает хеш-код для этой константы перечисления. На самом деле этот метод содержит только одну инструкцию, то есть «return super.hashCode ()», которая, в свою очередь, вызывает метод класса объекта hashCode ().

// Java-программа для демонстрации метода hashCode ()

public class Test

public static void main(String[] args)

Color c1 = Color.RED;

System.out.print( «hashcode of enum constant » + c1.name() + » : » );

Color c2 = Color.GREEN;

System.out.print( «hashcode of enum constant » + c2.name() + » : » );

final int compareTo (E obj) : этот метод «сравнивает» это перечисление с указанным объектом для заказа . Константы перечисления сравнимы только с другими константами перечисления того же типа.

// Программа Java для демонстрации метода CompareTo ()

public class Test

public static void main(String[] args)

Color c1 = Color.RED;

Color c2 = Color.GREEN;

Color c3 = Color.RED;

Color c4 = Color.BLUE;

System.out.print( «Comparing » +c1.name()+ » with » + c2.name() + » : » );

System.out.print( «Comparing » +c1.name()+ » with » + c3.name() + » : » );

System.out.print( «Comparing » +c4.name()+ » with » + c2.name() + » : » );

// Следующая инструкция выдает NullPointerException

// как аргумент метода CompareTo имеет значение null

// System.out.println (c4.compareTo (null));

статический T valueOf (Класс enumType, имя String): Этот метод возвращает перечисление константы указанного типа перечисления с указанным именем. Имя должно точно соответствовать идентификатору, используемому для объявления константы перечисления в этом типе.

// Java-программа для демонстрации метода valueOf ()

public class Test

public static void main(String[] args)

// получаем значение enum с указанным String

// используя метод valueOf

Color c1 = Color.valueOf( «RED» );

Color c2 = Color.valueOf( «GREEN» );

// Следующий оператор выдает IllegalArgumentException

// поскольку GrEEN не является константой enum

// Color c3 = Color.valueOf («GrEEN»);

// Следующая инструкция выдает NullPointerException

// как аргумент метода valueOf равен нулю

// Color c4 = Color.valueOf (null);

final Class getDeclaringClass () : Этот метод возвращает объект Class, соответствующий типу перечисления этой константы перечисления. Любые две константы перечисления e1 и e2 имеют одинаковый тип перечисления, если этот метод возвращает один и тот же объект Class для обоих.

// Java-программа для демонстрации метода getDeclaringClass ()

Ссылка на основную публикацию
Adblock
detector