Реализация Синглтона с перечислением (в Java)



Я читал, что можно реализовать Singleton в Java с помощью Enum, например:



public enum MySingleton {
INSTANCE;
}


но, как это работает? В частности,Object должен быть инстанцирован. Вот, как это MySingleton экземпляров? Кто это делает new MySingleton()?

822   6  

6 ответов:

этой

public enum MySingleton {
  INSTANCE;   
}

имеет неявный пустой конструктор. Давайте будем откровенными вместо

public enum MySingleton {
    INSTANCE;
    private MySingleton() {
        System.out.println("Here");
    }
}

если вы затем добавили еще один класс с main() методом

public static void main(String[] args) {
    System.out.println(MySingleton.INSTANCE);
}

вы увидите

Here
INSTANCE

enum поля являются константами времени компиляции, но они являются экземплярами их enum тип. И они создаются, когда на тип перечисления ссылаются в первый раз.

An enum тип-это особый тип class тип.

код enum объявление фактически компилируется в нечто вроде

public final class MySingleton {
    public final static MySingleton INSTANCE = new MySingleton();
    private MySingleton(){} 
}

когда ваш код впервые обращается INSTANCE класс MySingleton будет загружен и инициализирован JVM. Этот процесс инициализирует

в этой Java best practices book Джошуа блох, вы можете найти объяснил, почему вы должны применять Одноэлементное свойство с частным конструктором или перечисления типа. Глава довольно длинная, поэтому держу ее вкратце:

создание класса Синглтона может затруднить тестирование его клиентов, так как невозможно заменить макет реализации синглтона, если он не реализует интерфейс, который служит его типом. Рекомендуемый подход реализуется Синглтоны просто делают тип перечисления с одним элементом:

// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}

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

хотя этот подход еще не получил широкого распространения принятый, одноэлементный тип перечисления-лучший способ реализовать синглтон.

Как и все экземпляры перечисления, Java создает экземпляр каждого объекта при загрузке класса, с некоторой гарантией, что он создается ровно один раз за JVM. Подумайте о INSTANCE объявление как публичное статическое конечное поле: Java создаст экземпляр объекта при первом обращении к классу.

экземпляры создаются во время статической инициализации, которая определена в спецификация языка Java, раздел 12.4.

для чего это стоит, Джошуа Блох подробно описывает этот шаблон как пункт 3 из Эффективное Второе Издание Java.

С Синглтон Шаблон речь идет о том, чтобы иметь частный конструктор и вызывать некоторый метод для управления экземплярами (например, некоторые getInstance), в перечислениях у нас уже есть неявный частный конструктор.

Я не знаю как JVM или какой-нибудь контейнер контролирует экземпляры нашего Enums, но, похоже, он уже использует неявное Singleton Pattern разница в том, что мы не называем getInstance мы просто перечисление.

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

public enum MySingleton {
    INSTANCE;

    public void doSomething() { ... }

    public synchronized String getSomething() { return something; }

    private String something;
}

вы получаете доступ к методам синглтона по следующим линиям:

MySingleton.INSTANCE.doSomething();
String something = MySingleton.INSTANCE.getSomething();

использование перечисления вместо класса, как уже упоминалось в других ответах, в основном про потокобезопасную инициализацию Синглтона и гарантировать, что он всегда будет только одна копия.

и, пожалуй, самое главное, что такое поведение гарантируется самой JVM и спецификацией Java.

вот раздел из спецификации Java о том, как предотвращается несколько экземпляров экземпляра перечисления:

тип перечисления не имеет экземпляров, отличных от тех, которые определены его константами перечисления. Это Ошибка времени компиляции при попытке явного создания экземпляра типа перечисления. Метод final clone в Enum гарантирует, что константы enum никогда не могут быть клонированы, а специальная обработка механизмом сериализации гарантирует, что повторяющиеся экземпляры никогда не будут созданы в результате десериализации. Рефлексивное создание экземпляров типов перечислений запрещено. Вместе эти четыре вещи гарантируют, что никакие экземпляры типа перечисления не существуют за пределами тех, которые определены константами перечисления.

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

Comments

    Ничего не найдено.