Сегодня я просматривал некоторые вопросы на этом сайте и нашел упоминание об enum
использовании в шаблоне синглтона о предполагаемых преимуществах безопасности потоков для такого решения.
Я никогда не использовал enum
s, и я программирую на Java уже более двух лет. И, видимо, они сильно изменились. Теперь они даже полностью поддерживают ООП внутри себя.
Ответы:
Вы должны всегда использовать перечисления, когда переменная (особенно параметр метода) может взять только одно из небольшого набора возможных значений. Примерами могут быть такие вещи, как константы типа (статус контракта: «постоянный», «временный», «ученик») или флаги («выполнить сейчас», «отложить выполнение»).
Если вы используете перечисления вместо целых чисел (или строковых кодов), вы увеличиваете проверку во время компиляции и избегаете ошибок при передаче недопустимых констант, а также документируете, какие значения допустимы для использования.
Кстати, чрезмерное использование перечислений может означать, что ваши методы делают слишком много (часто лучше иметь несколько отдельных методов, а не один метод, который принимает несколько флагов, которые изменяют то, что он делает), но если вам нужно использовать флаги или коды типов, перечисления путь
Как пример, что лучше?
против
Вызов метода как:
затем становится:
Во втором примере сразу ясно, какие типы разрешены, документы и реализация не могут быть синхронизированы, и компилятор может применить это. Кроме того, неверный звонок, как
больше не возможно.
источник
you should *always* use enums when a variable can only take one out of a small set of possible values
. Использование постоянных значений в качестве «двоичного флага» (с логическимor
вводом) может быть полезно для приложений реального времени, где у вас мало памяти.Зачем использовать какую-либо функцию языка программирования? Причина, по которой у нас есть языки,
Перечисления улучшают как вероятность правильности, так и читабельности без написания большого количества шаблонов. Если вы хотите написать шаблонный шаблон, вы можете «смоделировать» перечисления:
Теперь вы можете написать:
Приведенный выше шаблон имеет тот же эффект, что и
Оба предоставляют одинаковый уровень проверки справки от компилятора. Boilerplate просто больше печатать. Но сохранение большого количества печати делает программиста более эффективным (см. 1), так что это полезная функция.
Это стоит по крайней мере еще по одной причине:
Смена операторов
Одна вещь, которую
static final
перечисленное выше моделирование перечисления не дает вам, это хорошиеswitch
случаи. Для перечислимых типов переключатель Java использует тип своей переменной, чтобы вывести область действия перечислений, поэтому дляenum Color
вышесказанного вам просто нужно сказать:Обратите внимание, что это не
Color.RED
в случаях. Если вы не используете enum, единственный способ использовать именованные величины сswitch
чем-то вроде:Но теперь переменная для хранения цвета должна иметь тип
int
. Хорошая проверка перечисления иstatic final
моделирования компилятором исчезла. Не счастлив.Компромиссом является использование скалярного члена в симуляции:
Сейчас же:
Но обратите внимание, еще более шаблонный!
Использование enum в качестве синглтона
Из вышеприведенного примера видно, почему перечисление предоставляет способ реализации синглтона. Вместо того чтобы писать:
а затем доступ к нему с
мы можем просто сказать
что дает нам то же самое. Мы можем уйти с этим , потому что Java перечислений будут реализованы в виде полных классов только с небольшим синтаксическим сахаром посыпают сверху. Это опять-таки менее шаблонно, но не очевидно, если идиома вам не знакома. Мне также не нравится тот факт, что вы получаете различные функции перечисления, даже если они не имеют особого смысла для синглтона:
ord
иvalues
т. Д. (На самом деле есть болееColor extends Integer
сложная симуляция, где это будет работать с switch, но это настолько сложно, что это даже больше ясно показывает, почемуenum
это лучшая идея.)Поток безопасности
Потоковая безопасность является потенциальной проблемой только тогда, когда синглтоны создаются лениво без блокировки.
Если много потоков вызывают
getInstance
одновременно, в то времяINSTANCE
как все еще нуль, может быть создано любое количество экземпляров. Это плохо. Единственное решение - добавитьsynchronized
доступ для защиты переменнойINSTANCE
.Однако приведенный
static final
выше код не имеет этой проблемы. Он создает экземпляр с нетерпением во время загрузки класса. Загрузка классов синхронизирована.enum
Одноточечно эффективно ленивая , потому что он никогда не инициализируется до первого использования. Инициализация Java также синхронизирована, поэтому несколько потоков не могут инициализировать более одного экземпляраINSTANCE
. Вы получаете лениво инициализированный синглтон с очень небольшим кодом. Единственный минус - довольно туманный синтаксис. Вам нужно знать идиому или полностью понимать, как работают загрузка и инициализация класса, чтобы знать, что происходит.источник
static final
поля инициализируются во время инициализации класса , а не во время загрузки. Это точно так же, как сenum
постоянной инициализацией (на самом деле они идентичны под капотом). Вот почему пытаться реализовать «умный» ленивый код инициализации для синглетонов всегда было бессмысленно, даже в первой версии Java.Помимо уже упомянутых вариантов использования, я часто нахожу перечисления полезными для реализации шаблона стратегии, следуя некоторым основным рекомендациям ООП:
Простейшим примером будет набор
Comparator
реализаций:Этот «шаблон» можно использовать в гораздо более сложных сценариях, широко используя все полезности, которые входят в enum: перебирая экземпляры, полагаясь на их неявный порядок, извлекая экземпляр по его имени, статические методы предоставляют правильный экземпляр для конкретного контекста и т. д. И все же у вас все это скрыто за интерфейсом, поэтому ваш код будет работать с пользовательскими реализациями без изменений на случай, если вы захотите что-то, что недоступно среди «опций по умолчанию».
Я видел, как это успешно применялось для моделирования концепции гранулярности по времени (ежедневно, еженедельно и т. Д.), Где вся логика была заключена в перечисление (выбор правильной гранулярности для данного временного диапазона, специфическое поведение, связанное с каждой гранулярностью как константа). методы и т. д.). И все же,
Granularity
как видно из сервисного уровня, это был просто интерфейс.источник
CASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }
. Еще одно преимущество, которое не упомянуто, заключается в том, что вы получаете надежную поддержку сериализации; постоянная форма содержит только имя класса и имя константы, независимо от деталей реализации ваших компараторов.То, что ни один из других ответов не охватил, что делает перечисления особенно мощными, - это возможность иметь шаблонные методы . Методы могут быть частью базового перечисления и переопределяться каждым типом. И, благодаря поведению, прикрепленному к enum, оно часто устраняет необходимость в конструкциях if-else или операторах switch, как показано в этом сообщении в блоге, - где
enum.method()
выполняется то, что первоначально будет выполняться внутри условного выражения . В этом же примере показано использование статического импорта с перечислениями, а также создание более чистого кода, подобного DSL.Некоторые другие интересные качества включают в себя тот факт, что перечисления обеспечивают реализацию
equals()
,toString()
иhashCode()
и реализуютSerializable
иComparable
.Для полного изложения всего, что может предложить перечисление, я настоятельно рекомендую Брюс Экель « Размышление в Java 4-е издание», в котором целая глава посвящена этой теме. Особенно яркими являются примеры игр «Камень, бумага, ножницы» (т.е. RoShamBo) в качестве перечислений.
источник
Из документов Java -
Типичным примером является замена класса набором частных статических конечных констант типа int (в пределах разумного числа констант) типом enum. По сути, если вы думаете, что знаете все возможные значения «что-то» во время компиляции, вы можете представить это как тип enum. Перечисления обеспечивают читаемость и гибкость над классом с константами.
Несколько других преимуществ, которые я могу придумать для типов enum. Они всегда являются одним экземпляром определенного класса enum (отсюда и концепция использования enum по мере появления синглтона). Другое преимущество заключается в том, что вы можете использовать перечисления в качестве типа в выражении switch-case. Также вы можете использовать toString () в перечислении, чтобы напечатать их как читаемые строки.
источник
DayOfWeek
enum теперь предопределен, встроен в Java 8 и более поздние версии как часть инфраструктуры java.time (и перенесен на Java 6 & 7 и на Android ).Вы можете использовать Enum для представления небольшого фиксированного набора констант или режима внутреннего класса, увеличивая читабельность. Кроме того, Enums может обеспечить определенную жесткость при использовании в параметрах метода. Они предлагают интересную возможность передачи информации конструктору, как в примере Planets на сайте Oracle, и, как вы обнаружили, также позволяют простой способ создания одноэлементного шаблона.
пример:
Locale.setDefault(Locale.US)
читает лучшеLocale.setDefault(1)
и обеспечивает использование фиксированного набора значений, показанного в IDE, когда вы добавляете.
разделитель вместо всех целых чисел.источник
Enum
s перечисляют фиксированный набор значений в самодокументируемой форме.Они делают ваш код более явным, а также менее подверженным ошибкам.
Почему бы не использовать
String
илиint
вместоEnum
констант?if
), чтобы убедиться, что ваш аргумент находится в допустимом диапазоне.String
любом случае, вам, вероятно, понадобится такой же объем памяти, чтобы использовать s (это зависит от сложностиEnum
).Более того, каждый из
Enum
экземпляров является классом, для которого вы можете определить свое индивидуальное поведение.Кроме того, они гарантируют безопасность потоков при создании экземпляров (при загрузке enum), что является отличным приложением для упрощения шаблона Singleton .
Этот блог иллюстрирует некоторые из его приложений, таких как конечный автомат для синтаксического анализатора.
источник
Полезно знать, что
enums
так же, как и другие классы сConstant
полями иprivate constructor
.Например,
Компилятор компилирует это следующим образом;
источник
enum
означает перечисление, то есть упоминание (несколько вещей) один за другим.ИЛИ
Например:
Преимущества enum:
для большего
источник
Что такое перечисление
Зачем использовать enum
Запись
источник
Помимо всего сказанного другими. В более старом проекте, над которым я работал, во многих отношениях между сущностями (независимыми приложениями) использовались целые числа, которые представляли собой небольшой набор. Было полезно объявить набор как
enum
статические методы для полученияenum
объектаvalue
и наоборот. Код выглядел чище, переключал удобство использования и облегчал запись в журналы.Создать
enum
объект из полученных значений (например, 1,2), используяProtocolType.fromInt(2)
Запись в журналы, используяmyEnumObj.name
Надеюсь это поможет.
источник
Enum наследует все методы
Object
класса и абстрактного классаEnum
. Таким образом, вы можете использовать его методы для отражения, многопоточности, сериализации, сопоставления и т. Д. Если вы просто объявите статическую константу вместо Enum, вы не сможете. Кроме того, значение Enum может быть передано и на уровень DAO.Вот пример программы для демонстрации.
источник
ENum расшифровывается как «Enumerated Type». Это тип данных, имеющий фиксированный набор констант, которые вы определяете сами.
источник
На мой взгляд, все ответы, которые вы получили до сих пор, действительны, но по своему опыту я бы выразил это в нескольких словах:
Используйте перечисления, если вы хотите, чтобы компилятор проверил правильность значения идентификатора.
В противном случае вы можете использовать строки, как вы всегда это делали (возможно, вы определили некоторые «соглашения» для своего приложения), и вы будете очень гибкими ... но вы не получите 100% -ную защиту от опечаток в ваших строках, и вы сможете их реализовать только во время выполнения.
источник
Используйте перечисления для БЕЗОПАСНОСТИ ТИПА, это языковая функция, поэтому вы обычно получаете:
У перечислений могут быть методы, конструкторы, вы даже можете использовать перечисления внутри перечислений и комбинировать перечисления с интерфейсами.
Представьте перечисления как типы для замены четко определенного набора констант int (которые Java «унаследовала» от C / C ++) и в некоторых случаях для замены битовых флагов.
Книга Effective Java 2nd Edition содержит целую главу о них и более подробно. Также см. Этот пост переполнения стека .
источник
Java позволяет ограничить переменную одним из нескольких предопределенных значений, другими словами, одним значением из перечисленного списка. Использование
enums
может помочь уменьшить количество ошибок в вашем коде. Вот примерenums
вне класса:Это ограничивает
coffeesize
к иметь либо:BIG
,HUGE
или вOVERWHELMING
качестве переменной.источник
Enum? Зачем его использовать? Я думаю, что это более понятно, когда вы будете его использовать. У меня такой же опыт.
Скажем, у вас есть операция создания, удаления, редактирования и чтения базы данных.
Теперь, если вы создаете enum как операцию:
Теперь вы можете объявить что-то вроде:
Таким образом, вы можете использовать его по-разному. Всегда хорошо иметь enum для конкретных вещей, так как работа с базой данных в приведенном выше примере может контролироваться проверкой currentOperation . Возможно, можно сказать, что это можно сделать с помощью переменных и целочисленных значений. Но я считаю, что Enum - более безопасный и программистский путь.
Другое дело: я думаю, что каждый программист любит логическое , не так ли? Потому что он может хранить только два значения, два конкретных значения. Таким образом, можно думать, что Enum имеет такой же тип средств, где пользователь будет определять, сколько и какой тип значения он будет хранить, просто немного по-другому. :)
источник
До сих пор мне никогда не приходилось использовать перечисления. Я читал о них с тех пор, как они были введены в версии 1.5 или версии тигра, как это было отозвано в тот же день. Они никогда не решали «проблему» для меня. Для тех, кто использует это (и я вижу, что многие из них делают), я уверен, что это определенно служит какой-то цели. Просто мои 2 фунта.
источник
Здесь есть много ответов, просто хочу указать два конкретных:
1) Использование в качестве констант в
Switch-case
утверждении. Переключатель case не позволит вам использовать объекты String для case. Перечисления пригодятся. Больше: http://www.javabeat.net/2009/02/how-to-use-enum-in-switch/2) Реализация
Singleton Design Pattern
- Enum снова приходит на помощь. Использование здесь: Каков наилучший подход для использования Enum в качестве синглтона в Java?источник
То, что дало мне момент ах-ха, это осознание: у Enum есть частный конструктор, доступный только через публичное перечисление:
источник
Что касается меня, чтобы сделать код читаемым в будущем, то наиболее полезный применимый случай перечисления представлен в следующем фрагменте:
источник
По своему опыту я видел, что использование Enum иногда приводит к тому, что системы очень трудно изменить. Если вы используете Enum для набора доменных значений, которые часто меняются, и у него есть много других классов и компонентов, которые зависят от него, вы можете подумать не использовать Enum.
Например, торговая система, которая использует Enum для рынков / бирж. Существует множество рынков, и почти наверняка будет много подсистем, которым необходим доступ к этому списку рынков. Каждый раз, когда вы хотите, чтобы новый рынок был добавлен в вашу систему, или если вы хотите удалить рынок, возможно, что все под солнцем придется перестраивать и выпускать.
Лучшим примером будет что-то вроде типа категории продукта. Допустим, ваше программное обеспечение управляет запасами для универмага. Существует много категорий товаров и множество причин, по которым этот список категорий может измениться. Менеджеры могут захотеть снабдить новой линейкой продуктов, избавиться от других линий продуктов и, возможно, время от времени реорганизовывать категории. Если вам нужно перестроить и заново развернуть все свои системы просто потому, что пользователи хотят добавить категорию продукта, то вы взяли что-то, что должно быть простым и быстрым (добавление категории), и сделали это очень трудным и медленным.
В итоге, перечисления хороши, если данные, которые вы представляете, очень статичны во времени и имеют ограниченное количество зависимостей. Но если данные сильно меняются и имеют много зависимостей, вам нужно что-то динамическое, что не проверяется во время компиляции (например, таблица базы данных).
источник
Синглтон на основе перечисления
Этот подход реализует синглтон, используя преимущества гарантии Java, что любое значение enum создается только один раз в программе Java, и enum обеспечивает неявную поддержку безопасности потоков. Так как значения перечисления Java являются глобально доступными, поэтому его можно использовать как одиночный.
Как это работает? Ну, вторая строка кода может рассматриваться примерно так:
И мы получаем старый добрый ранний инициализированный синглтон.
Помните, что, поскольку это enum, вы всегда можете получить доступ к экземпляру через
преимуществаSingleton.INSTANCE
:valueOf
метод с десериализованным именем для получения желаемого экземпляра.Enum
класс java . Причина, по которой отражение не может быть использовано для создания экземпляров объектов типа enum, заключается в том, что спецификация java запрещена, и это правило закодировано в реализацииnewInstance
методаConstructor
класса, который обычно используется для создания объектов посредством отражения:map
. Вместо того, чтобы иметь по одному экземпляру на приложение (например,java.lang.Runtime
), многотонный шаблон обеспечивает один экземпляр на ключ .Существует несколько реализаций синглтон-паттернов, каждый из которых имеет свои преимущества и недостатки.
Подробное описание каждого из них слишком многословно, поэтому я просто поместил ссылку на хорошую статью - Все, что вы хотите знать о Синглтоне
источник
Я бы использовал перечисления в качестве полезного инструмента отображения, избегая множественных
if-else
при условии, что некоторые методы реализованы.Так что метод
by(String label)
позволяет вам получить значение Enumerated неперечисленным. Кроме того, можно изобрести отображение между 2 перечислениями. Можно также попробовать «1 ко многим» или «многие ко многим» в дополнение к «одно к одному» по умолчанию отношениеВ конце концов,
enum
это класс Java. Таким образом, у вас может бытьmain
метод внутри него, который может быть полезен, когда нужно выполнить некоторые операции отображенияargs
сразу.источник
Вместо того чтобы делать кучу объявлений const int
Вы можете сгруппировать их все в 1 enum
Так что все это организовано общей группой, к которой они принадлежат
источник
Перечисления похожи на классы. Как и класс, он также имеет методы и атрибуты.
Различия с классом: 1. константы перечисления являются общедоступными, статическими, конечными. 2. перечисление не может использоваться для создания объекта и не может расширять другие классы. Но он может реализовать интерфейсы.
источник
В дополнение к @BradB Ответ:
Это так верно ... Странно, что это единственный ответ, который упоминает об этом. Когда новички обнаруживают перечисления, они быстро воспринимают это как фокус для проверки правильности идентификатора компилятора. И когда код предназначен для использования в распределенных системах, они плачут ... через месяц. Поддерживать обратную совместимость с перечислениями, которые содержат нестатический список значений, - реальная проблема, и боль. Это связано с тем, что когда вы добавляете значение в существующее перечисление, его тип изменяется (несмотря на то, что имя не меняется).
«Хо, подожди, это может выглядеть как один и тот же тип, верно? В конце концов, они перечисления с одним и тем же именем - и не являются ли перечисления просто целыми числами под капотом?» И по этим причинам ваш компилятор, скорее всего, не будет помечать использование одного определения самого типа там, где ожидалось другое. Но на самом деле они (в наиболее важных отношениях) разные типы. Самое главное, они имеют разные домены данных - значения, которые являются приемлемыми для данного типа. Добавляя значение, мы эффективно изменили тип перечисления и поэтому нарушаем обратную совместимость.
В заключение: используйте его, когда хотите, но, пожалуйста, убедитесь, что используемая область данных является конечным, уже известным, фиксированным набором .
источник