Я прочитал, что это можно реализовать Singleton
в Java, используя Enum
такие как:
public enum MySingleton {
INSTANCE;
}
Но как работает выше? В частности, Object
должен быть создан экземпляр. Здесь, как MySingleton
создается экземпляр? Кто делает new MySingleton()
?
INSTANCE
так же, какpublic static final MySingleton INSTANCE = new MySingleton();
.Ответы:
Это,
имеет неявный пустой конструктор. Вместо этого сделайте это явным,
Если вы затем добавили другой класс с помощью
main()
метода, какВы бы увидели
enum
поля являются константами времени компиляции, но они являются экземплярами своегоenum
типа. И они создаются при первом обращении к типу перечисления .источник
private
Модификатор не имеет никакого значения дляenum
конструкторы и полностью избыточные.enum
Тип представляет собой особый типclass
.Ваш
enum
будет фактически скомпилирован в нечто вродеПри первом обращении к коду
INSTANCE
классMySingleton
будет загружен и инициализирован JVM. Этот процесс инициализируетstatic
поле выше один раз (лениво).источник
public enum MySingleton { INSTANCE,INSTANCE1; }
и затемSystem.out.println(MySingleton.INSTANCE.hashCode()); System.out.println(MySingleton.INSTANCE1.hashCode());
он печатает разные хэш-коды. Означает ли это, что два объекта MySingleton созданы?enum
константы.В этой книге о лучших практиках Java Джошуа Блоха вы найдете объяснение, почему вам следует применять свойство Singleton с помощью частного конструктора или типа Enum. Эта глава довольно длинная, поэтому она должна быть краткой:
Создание класса Singleton может затруднить тестирование его клиентов, поскольку невозможно заменить фиктивную реализацию на singleton, если он не реализует интерфейс, который служит его типом. Рекомендуемый подход - реализовать Singletons, просто создав тип enum с одним элементом:
Этот подход функционально эквивалентен общедоступному полевому подходу, за исключением того, что он более лаконичен, предоставляет механизм сериализации бесплатно и обеспечивает железную гарантию против множественных экземпляров, даже перед сложными атаками сериализации или отражения.
источник
Как и все экземпляры enum, Java создает каждый объект при загрузке класса с некоторой гарантией, что он создается только один раз для каждой JVM . Думайте об
INSTANCE
объявлении как об открытом статическом конечном поле: Java будет создавать экземпляр объекта при первом обращении к классу.Экземпляры создаются во время статической инициализации, которая определена в Спецификации языка Java, раздел 12.4 .
Что бы это ни стоило, Джошуа Блох подробно описывает этот шаблон как пункт 3 Effective Java Second Edition .
источник
Поскольку Singleton Pattern - это наличие частного конструктора и вызов некоторого метода для управления экземплярами (например, некоторых
getInstance
), в Enums у нас уже есть неявный закрытый конструктор.Я точно не знаю, как JVM или какой-то контейнер управляет экземплярами нашего
Enums
, но кажется, что он уже использует неявныйSingleton Pattern
, разница в том, что мы не называем agetInstance
, мы просто вызываем Enum.источник
Как в некоторой степени упоминалось ранее, enum - это класс java со специальным условием, что его определение должно начинаться хотя бы с одной «константы enum».
Кроме того, и то, что перечисления не могут быть расширены или использованы для расширения других классов, перечисление является классом, как любой класс, и вы используете его, добавляя методы под определениями констант:
Вы получаете доступ к методам синглтона по этим направлениям:
Использование перечисления вместо класса, как было упомянуто в других ответах, в основном касается поточно-ориентированной реализации синглтона и гарантии того, что он всегда будет только одной копией.
И, возможно, самое главное, что это поведение гарантировано самой JVM и спецификацией Java.
Вот раздел из спецификации Java о том, как предотвратить несколько экземпляров экземпляра enum:
Стоит отметить, что после создания экземпляра любые проблемы безопасности потока должны обрабатываться, как и в любом другом классе с ключевым словом synchronized и т. Д.
источник