• ,

15 вопросов для собеседования разработчиков, относительно Enum в Джаве (с ответами!)

Перечисление (Enum) было введено в Java 5 и с тех пор оно стало весьма популярно среди разработчиков Java. Оно широко используется в различных Java-приложениях. Поскольку Enum в Java намного универсальнее, чем в C или C ++, оно также представляет множество интересных вариантов использования, пару из которых, вы видели в статье 10 способов использовать Enum в Java.

Но, несмотря на такую популярность, многие Java-программисты по-прежнему не знают о функциональности, предоставляемой Enum и тонкостей использования Enum в Java коде. Это стало понятно из вопросов нескольких читателей, спрашивающих, например, о возможности Enum реализовать интерфейс в Java или Почему мы не можем создать экземпляры Enum за пределами Enum, отметив, что об этом их спрашивали на собеседовании. Это подвигло на сбор списка часто задаваемых вопросов в Java Enum, которые не только помогают преуспеть в интервью, но и открыть новые пути для обучения. Как говорилось раньше, часто вопросы на собеседовании заставляют вас воспринимать тему более серьёзно, что не так уж плохо, и, учитывая мощь и полезность Enum, пора уже вам стать мастером перечислений.

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

1) Может ли Enum наследовать (implement) интерфейс в Java?
Да, Enum может наследовать интерфейсы. Поскольку Enum тип схож с классом и интерфейсом, он может наследовать интерфейс. Это даёт поразительную гибкость в использовании Enum в качестве специальной реализации в некоторых случаях. Вот неплохой пример использования Enum в таком качестве.

2) Может ли Enum наследовать (extends) класс?
Нет, не может! Неожиданно, поскольку ранее говорилось что Enum тип похож на класс или интерфейс в Java. Ну, это главная причина, почему такой вопрос задают сразу за предыдущим. Поскольку Enum уже наследуется от абстрактного класса java.lang.Enum, понятно, что другой класс наследовать не удастся, поскольку Java не поддерживает множественное наследование классов. Благодаря наследованию от java.lang.Enum, все перечисления имеют методы ordinal(), values() или valueOf().

3) Как создать Enum без экземпляров объектов? Возможно ли это без ошибки компиляции?
Это один из тех хитрых вопросов, которые так любят интервьюеры. Поскольку Enum видится коллекцией определённого количества объектов, как дни недели или месяцы в году получить Enum без ничего кажется подозрительным. Но да, вы можете создать Enum без экземпляров, например создавая утилитарный класс. Это ещё один инновационный способ использовать Enum:
public enum MessageUtil{
;  // required to avoid compiler error, also signifies no instance

public static boolean isValid() {
        throw new UnsupportedOperationException("Not supported yet.");
}

}

4) Можем ли мы переопределить метод toString() для Enum? Что будет, если не будем переопределять?
Конечно вы можете переопределить метод toString() у Enum, как и любого класса, наследующего java.lang.Object и имеющего метод toString() в доступности, и даже если вы не станете этого делать, ничего не потеряете, поскольку абстрактная основа класса Enum сделает это за вас, и вернёт имя, являющееся именем экземпляра Enum. Вот код метода toString() из класса Enum:
public String toString() {
        return name;
 }


name задано, когда компилятор выделяет код для создания перечисления в ответ на создание экземпляра в самом классе Enum, наравне с созданием порядкового числительного в конструкторе из класса java.lang.Enum:
protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
}

Это единственный конструктор для создания перечисления, который вызывается компилятором в ответ на декларирование Enum в программе.

5) Можем ли мы создать экземпляр Enum вне Enum? Почему нет?
Вы не можете создавать экземпляры Enum вне границ Enum, поскольку у Enum нет public конструктора, и компилятор не позволит вам внести любой подобный конструктор. Так как компилятор генерирует большинство кода в ответ на декларацию Enum типа, он не допускает public конструкторов внутри Enum, что заставляет объявлять экземпляры Enum внутри себя.

6) Можем ли мы указать конструктор внутри Enum?
Этот вопрос часто следует за предыдущим. Да, вы можете, но помните, что подобное возможно лишь с указанием private или package-private конструкторов. Конструкторы с public и protected — не допустимы в Enum. Вот тут можно посмотреть пример.

7) Какая разница сравнивать Enum при помощи == или метода equals()?
Это очень обширный и хитрый вопрос, который рассматривается подробно здесь.

8) Что делает метод ordinal() в Enum?
Метод ordinal() (порядковый) возвращает порядок, в котором экземпляры Enum обозначены внутри Enum. Например, в DayOfWeek Enum, вы можете указать дни по порядку:
public enum DayOfWeek{
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

и если мы вызовем метод DayOfWeek.MONDAY.ordinal(), он вернёт 0 — что значит первый экземпляр. Этот метод весьма полезен для предоставления порядка в соответствии с реальным положением вещей: т. е. указывая, что TUESDAY (вторник) идёт после MONDAY (понедельника), и перед WEDNESDAY (средой). Точно так же вы можете использовать перечисление для представления месяцев года, где Февраль идёт после Января, но предшествует Марту. Все пользовательские перечисления наследуют этот метод из абстрактного класса java.lang.Enum, и они устанавливаются компилятором, вызывая protected конструктор из java.lang.Enum, который принимает имя и порядковый номер.

9) Можно использовать Enum с TreeSet или TreeMap в Java?
Это действительно интересный вопрос по Enum, и его любят задавать для проверки глубины знаний. Пока вы не загляните в код java.lang.Enum, вы скорей всего не будете знать, что Enum наследует интерфейс Comparable, который является главным требованием для использования в упорядоченных коллекциях, как TreeSet и TreeMap. Поскольку Enum по умолчанию наследует интерфейс Comparable, он может использоваться с TreeSet и TreeMap.

10) Какая разница между ordinal() и compareTo() в Enum?
Это прямое следование из предыдущего вопроса: на самом деле, compareTo() имитирует порядок, предоставляемый методом ordinal(), являющийся естественным порядком Enum. Если коротко, Enum ограничивает сравнения в порядке их объявления. Так же, стоит помнить, что данные константы сравнимы только с другими константами того же типа — сравнение разных типов констант может привести к ошибке компилятора.

11) Можно ли использовать Enum в switch case?
Да, вы можете. Мало того, это одна из главных полезностей использования Enum. Поскольку экземпляры Enum компилируют временную константу, вы можете без опаски внедрять их внутрь case и switch. Вот например код с днями недели:
public void developerState(DayOfWeek today){
        switch(today){
            case MONDAY:
                System.out.println("Hmmmmmmmm");
                break;
            case TUESDAY:
                System.out.println("Hmmmm");
                break;
            case FRIDAY :
                System.out.println("Yeahhhhhh");
                break;
        }     
}


Enum и Switch отлично дополняют друг друга, в особенности если Enum содержит небольшое количество устойчивых констант, например, семь дней недели, 12 месяцев года и т. д. Посмотрите на другие примеры использования swith case с Enum.

12) Как пройтись по всему экземпляру Enum?
Если вы открывали java.lang.Enum, то знаете, что метод values() возвращает массив всех констант Enum. Поскольку каждое перечисление наследует java.lang.Enum, они имеют метод values(). Используя его, вы можете пройтись по всем константам перечисления определённого типа. Посмотрите на примеры такого проходя с циклом foreach и методом values().

13) Какие плюсы и минусы использования Enum в качестве синглтона?
Enum предоставляет быстрый ярлык для воплощения паттерна синглтона, и поскольку об этом сказано даже в книге «Эффективная Java», такой выбор весьма популярен. На первый взгляд, синглтон Enum многообещающ и весьма удобен, например контролирует создание экземпляра, безопасно сериализуется и прежде всего, легко создать потокобезопасный синглтон с использованием Enum. Вам не нужно больше заботиться о двойной проверке волатильности переменных. Более подробно о плюсах и минусах использования такого подхода тут.

14) Какая выгода использовать Enum вместо паттернов перечисления int и перечисления String?
Если вы программируете более 5 лет, и ещё застали JDK 1.3 или 1.4, вы будете на короткой ноге с паттернами перечисления String и int, где используется public static final префикс констант для представления коллекции общеизвестных фиксированных количеств вещей, как Дни Недели. Тут возникает множество проблем: у вас нет независимости типа Enum, поскольку переменная String отвечающая за день недели может принимать любое произвольное значение. Точно так же перечисляемый int может принимать любое значение, и компилятор спокойно проглотит это. А с использованием Enum, вы получаете безопасность типов, которые компилятор проверяет для вас. На эту тему есть несколько интересных мыслей в «Эффективная Java», которую рекомендуется прочитать всем разработчикам на Java.

15) Как преобразовать String в Enum?
Это ежедневный вопрос, встающий из-за популярности применения String и Enum в разработке приложений Java. Лучший способ преобразовать Enum в String, это определить фабричный метод в самом Enum, который будет брать аргументы String и возвращать в качестве Enum. Вы так же можете пожелать игнорировать регистр. Вот несколько примеров по превращению строк в перечисления.

Вот и подошёл к концу наш список из 15 вопросов (и ответов) о Enum. Но помните: чтения не достаточно для обучения, это только первый шаг. Что бы получить выгоду от перечислений, попытайтесь найти, где можно использовать Enum в вашем проекте — это даст вам реальный опыт, и с этим опытом вы выучите больше, чем на примерах, поскольку встретите больше проблем, справляясь с которыми, обработаете более сложные и подробные требования. На эти вопросы о Enum стоит обратить внимание для тестирования ваших знаний, особенно если вы спешите на собеседование, и времени на детальное погружение во вселенную Enum просто нет.

1 комментарий

IvanRychkov
  • IvanRychkov
  • 0
  • Комментарий отредактирован 2015-10-15 13:04:20 пользователем IvanRychkov
Спасибо, интересно было почитать, только в 15 не понял: String в Enum или наоборот?
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.