Oc-windows.ru

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

Java enum ordinal

Перечисления 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-Всемогущий.
— Как так, Всемогущий? — перебивает Голос с возмущением. — Это только перечисление!

— Ага, — отвечает разраб, Но не только.
— Докажи!
— Enum как гвозди, утильным могёт.

— Во так чудеса, но… Наследника у него нет!
— А это как посмотреть. А кого считать Наследником? Scala? Kotlin?
— Давай пример, не дожидаясь пока разраб завершит свой вопрос

Читать еще:  Переопределение tostring java

— Да уж, интересные Вы ребята, прогеры — уже улыбаясь, говорит Голос, — Но малова-то будет
Почесав репу, Иван продолжил:
— Enum-то у нас фабрика!
— Не, было уже.
Пришлось, Ивану последний козырь достать:
— Enum-Синглтон, точно!

Выбери свое

— Джошуа Блох говорит*, что это лучшая реализация Синглтона.
— Ну а ты?
— А что я? Это, это — это синглтон-фабрика, для хранения одного единственного элемента, тить колотить.

Это точка для доступа к массиву для хранения одного единственного элемента, тить колотить.

Это наследник класса . , — хотел было продолжить Иван, но был приятно удивлен:
— Проходи.

Немного выводов

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

  • Перечисление и данные
  • Каркас для утилитного класса
  • Каркас для синглтона класса + антипатерн прилагается
  • Каркас для фабрики

Эксперимент

Я решил понять, сколько можно максимально сгенерировать элементов перечислений. Мой собственный ответ и реальность настолько разошлись, что я усомнился в своих знаниях. Прежде чем Вы посмотрите ниже, попытайтесь дать ответ самостоятельно. Упростим, скажите хотя бы порядок? Вот код, который я использовал для генерации класса перечислений (на быструю руку):

Вы уже предположили? Так вот, на семерочке мне удалось сгенерировать всего 2746 элементов перечислений. А дальше вот это:

Но, так как я раскатал губу в 4 этажа, сначала я получил такую ошибку:

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

1. Что такое перечисления?

В Java 5 были введены перечисления, которые создаются с использованием ключевого слова enum . Перечисления указывают возможные значения для какого-то явления. Например, вы открыли кофейню, в которой продаются три возможные варианты кофе — BIG , HUGE и OVERWHELMING . Других вариантов быть не может. Если задавать значения с помощью String , можно выбрать любое другое значение, например — MIDDLE , SMALL . Задавая перечисления, вы ограничиваете возможные варианты:

В простейшей форме перечисления — это список именованных констант. Каждая константа перечисления ( BIG , HUGE и OVERWHELMING ) является объектом класса, в котором она определена. Константы перечисления являются static final и не могут быть изменены после создания.

Перечисления можно представить в виде класса, содержащего константы, например:

Но у перечислений гораздо больше преимуществ по сравнению с таким классом. Какие — рассмотрим чуть позже.

2. Использование в операторе switch

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

3. Класс java.lang.Enum

Перечисление в Java относится к типу класса, но перечисление НЕ может наследоваться от другого класса и НЕ может быть суперклассом.

Все перечисления автоматически наследуют от класса java.lang.Enum . В этом классе определяется ряд методов, доступных для использования во всех перечислениях: ordinal() , compareTo() , equals() , values() и valueOf() .

Перечисления также неявно наследуют интерфейсы Serializable и Comparable .

Рассмотрим методы класса java.lang.Enum .

3.1. Метод values()

Метод values() возвращает массив, содержащий список констант перечислимого типа:

3.2. Метод valueOf()

Статический метод valueOf() возвращает константу перечислимого типа, значение которой соответствует символьной строке, переданной в качестве аргумента. Можно сказать, что этот метод преобразует значение String в перечисление:

3.3. Метод ordinal()

Вызвав метод ordinal() , можно получить значение, которое обозначает позицию константы в списке констант перечислимого типа. Порядковые значения начинаются с нуля:

Читать еще:  Java округление double до двух знаков

3.4. Метод compareTo()

С помощью метода int compareTo(типПеречисления e) можно сравнить порядковые значения двух констант одного и того же перечислимого типа. Метод возвращает значение типа int .

Если порядковое значение вызывающей константы меньше, чем у константы е ( this ), то метод compareTo() возвращает отрицательное значение.

Если порядковые значения обеих констант одинаковы ( this == e ), возвращается нуль.

Если порядковое значение вызывающей константы больше, чем у константы е ( this > e ), то возвращается положительное значение.

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

3.5. Метод equals()

Вызвав метод equals() , переопределяющий аналогичный метод из класса Object, можно сравнить на равенство константу перечисления с любым другим объектом. Но оба эти объекта будут равны только в том случае, если они ссылаются на одну и ту же константу из одного и того же перечисления. Простое совпадение порядковых значений не вынудит метод equals() возвратить логическое значение true , если две константы относятся к разным перечислениям.

При сравнении констант перечислений, можно использовать оператор » == » — он будет работать также, как и метод equals() .

4. Возможности перечисления

Создать экземпляр перечисления с помощью оператора new нельзя, но в остальном перечисление обладает всеми возможностями, которые имеются у других классов. А именно — в перечисления можно добавлять конструкторы, переменные и методы. Конструкторы перечисления являются private по умолчанию.

Допустим мы хотим задать размер нашей чашки кофе в миллилитрах. Для этого введем переменную ml в перечисление и геттер метод getMl() . Добавим конструктор, на вход которого будем задавать значение для миллилитров.

Обратите внимание, что при объявлении конструктора не указан модификатор доступа — он private по умолчанию. Уже говорилось, что нельзя создавать объекты перечисления используя оператор new . Как же тогда вызвать наш конструктор? Для вызова конструктора перечисления после указания константы ставятся круглые скобки, в которых передается нужное значение.

Методы для перечисления вызываются так же, как и для обычного объекта. В следующем классе мы перебираем все константы нашего перечисления и для каждого вызываем метод getMl() :

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

5. Объявление перечислений

Перечисления могут быть объявлены: отдельным классом или как член класса. Но НЕ могут быть объявлены внутри метода.

В этом пример перечисление CoffeeSize объявлено внутри класса Coffee3 :

Для обращения к такому перечислению необходимо использовать имя внешнего класс:

6. Переопределение методов

Для перечислений можно переопределять методы, но это не совсем обычное переопределение.

Добавим в наше перечисление метод getLid() , который возвращает код крышки для чашки кофе. Для всех констант подходит код B , который возвращает этот метод, кроме константы OVERWHELMING . Для OVERWHELMING чашки нужен код A . Переопределим метод getLid() для этой константы. Как это делается? После объявления константы открываем фигурные скобки, в которых и переопределяем этот метод. Если необходимо переопределить несколько методов, это делается в этих же фигурных скобках.

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

7. Перечисления и интерфейсы

Перечисления не могут наследовать другие классы, но могут реализовывать интерфейсы. Например, следующее перечисление реализует интерфейс Runnable :

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

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

Читать еще:  Integer compare java

Синтаксис перечисления 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 запрещено. Так следующий пример не будет скомпилирован:

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