Перечисления Enum в Java - Часть 2

Facebooktwittergoogle_plustumblrFacebooktwittergoogle_plustumblr

Данная статья:

  • написана командой Vertex Academy. Надеемся, что она Вам будет полезна. Приятного прочтения!
  • это одна из статей из нашего "Самоучителя по Java" 
  • Данная статья предполагает, что Вы уже хорошо знаете ООП.

В предыдущей статье (Урок 66: Перечисления Enum в Java) мы рассмотрели что такое Enum в Java. Абстрактный класс Enum появился в 5-й версии Java. Теперь, благодаря абстрактному классу Enum мы можем быстро и легко создавать перечисления без написания повторяющегося кода.

В этой статье мы рассмотрим на конкретных примерах следующее:

1. К Enum можно применять методы:

  • name() - возвращает имя
  • ordinal() - возвращает порядковый номер
  • equals()
  • hashCode()
  • toString()
  • finalize()
  • clone()
  • values()
  • valueOf()

2. Enum реализовывает интерфейс Comparable

3. Enum реализовывает интерфейс Serializable


Иииииии сразу в бой 🙂 Создадим простой enum Color

Методы name() и ordinal()

У каждого enum есть имя и порядковый номер. Получить их можно с помощью методов name() и ordinal()

Посмотрим как это реализовано в классе Enum

Пояснения:

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

Возникает вопрос, а где же ключевое слово extends возле декларации перечисления Color? Все дело в ключевом слове enum, именно оно даёт понять программе, что вы хотите не просто класс, а именно перечисление, что и дает Вам уйму возможностей.

Методы equals(), hashcode(), toString(), finalize() и clone()

Enum переопределяет базовые методы класса Object. Так что их можно использовать сразу же в наших перечислениях.

Пример 1: equals()

Пример 2:  hashCode()

Поскольку мы использовали hashCode(), каждый раз будет выводиться разное значение, сгенерированное автоматически. Когда мы запускали код, получили числа 366712642 и 1829164700. Вы наверняка получите другие числа.

Пример 3: toString()

Посмотрим как они реализованы в классе Enum

Пояснения:

  • метод toString() возвращает имя значения перечисления. Назвали значение WHITE, это же значение и получим при вызове toString() или name();
  • метод equals() сравнивает значения перечислений по ссылкам. Почему? Потому, что значения в перечислениях являются константными (уникальными), существует всего один экземпляр цвета RED, один цвета GREEN и один BLUE, значит ссылка на этот экземпляр будет всего одна, значит их можно сравнивать с помощью ==. Вы можете сами убедиться в этом, написав Color.RED == Color.RED или Color.GREEN == COLOR.BLUE;
  • метод hashCode() использует стандартную реализацию из класса Object.

Пример 4: finalize(), clone()

Пояснения:

  • метод finalize() пустой, а это значит, что не нужно закрывать "ресурсы" перед сборщиком мусора.  Мы говорим о тех "ресурсах", которые используются в try-with-resources. Да и вообще метод finalize() пережиток прошлых лет и в Java 9 данный метод уже помечен как @Deprecated (устаревший метод, который уберут в последующих реализациях);
  • метод clone() мы можем вызвать только внутри самого перечисления т.к. он помечен ключевым словом protected. Но даже если мы попытаемся сделать это, то ничего мы не получим, кроме CloneNotSupportedException. Нужно это для того чтобы нельзя было создать несколько экземпляров одного и того же перечисления. Ведь в реальной жизни у нас нет двух цифр "1", нет двух значений скорости света, так и с перечислениями.

Метод values() - позволяет получить массив всех значений Enum

Сделать это можно с помощью метода values()

Посмотрим на реализацию метода values() в классе Enum

Пояснения:

  • полной реализации метода в классе Enum нет, так как он синтетический (искусственно добавляется во время компиляции). Из документации узнаем, что метод просто возвращает массив всех значений перечисления в порядке их объявления.

Метод valueOf() - позволяет получить значения перечисления по его строковому представлению

Для получения значение перечисления по его строковому представлению у Enums есть метод valueOf(). Посмотрим на его использование

Если же такого значения в перечислении нет, то мы получим IllegalStateException

Посмотрим на реализацию метода valueOf() в классе Enum

Пояснения:

  • как и в случае с values() этот метод тоже синтетический и поэтому полной реализации данного метода в классе Enum нет. В официальной документации написано, что метод просто возвращает значение перечисления по его строковому представлению. Проверка строгая, поэтому никаких пробелов вначале, в конце или между буквами не должно быть.

Есть еще один способ получить значение перечисления

но он является менее распространённым.

Рассмотрим его подробнее:

Пояснения:

  • метод enumConstantDirectory() возвращает Map, где ключ - строковое значение перечисления, а значение - реальное значение перечисления;
  • если мы нашли нужное значение в Map - возвращаем его;
  • если мы передали null в метод valueOf() - обратно получим NullPointerException;
  • если же значения, которое мы указали в valueOf() нет - мы получим IllegalArgumentException.

Enum реализовывает интерфейс Comparable

Что такое интерфейс Comparable мы рассматривали в статье "Интерфейсы Comparable и Comparator".

Зачем же Enum реализовывает интерфейс Comparable? Сделано это для того, чтобы перечисления можно было сравнивать друг с другом при сортировке. При этом сравнение происходит по ordinal() перечисления. Вспомним порядок объявления значений в Color

Теперь посмотрим на сравнение элементов перечисления с помощью метода compareTo()

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

  • Число означает, что значение GREEN находится правее на одну позицию от значения RED
  • Число означает, что значение GREEN равно само себе
  • Число -1 означает, что значение GREEN находится левее от значения BLUE на одну позицию
  • Число -2 означает, что значение RED находится левее от значения BLUE на две позиции

А теперь посмотрим на использование в коллекции List

Метод Collections.sort(colors) отсортировал список colors благодаря тому, что Enum реализовывают интерфейс Comparable. Посмотрим на реализацию метода compareTo() в классе Enum

Пояснения:

  • сравнивать перечисления можно только между своими типами. Нельзя сравнивать перечисления типа Color с перечислением типа Car. Мало того, что компилятор не даст вам это сделать с помощью своих подсказок так еще и в самом методе есть проверка на тип класса перечислений.

Enum реализовывает интерфейс Serializable

Но как и в случае с clone() воспользоваться мы им не можем

Пояснения:

  • причина того, что эти методы приватные да и к тому же бросают исключения при их вызове так же, что и в случае с clone(). Если бы эта возможность была открыта, тогда легко можно было бы сохранить перечисление в файл, затем считать его обратно и получить на выходе два экземпляра одного значения перечисления. Этот как два значения числа "1";

На этом урок заканчивается

В следующей статье мы разберем:

  • конструкторы, переменные и собственные методы в перечислениях;
  • специальные коллекции для перечислений.

Спасибо, что были с нами! 🙂


Надеемся, что наша статья была Вам полезна.  Можно записаться к нам на курсы по Java на сайте.

Facebooktwittergoogle_plustumblrFacebooktwittergoogle_plustumblr

Facebooktwittergoogle_plustumblrFacebooktwittergoogle_plustumblr
Самоучители--узнать детальнее--