Джош Блох рекомендует использовать одноэлементный тип enum
для реализации синглетонов (см. Effective Java 2nd Edition, пункт 3: принудительное использование свойства singleton с помощью частного конструктора или типа enum ).
Некоторые люди думают, что это взлом, поскольку он явно не выражает намерения, но работает.
Следующий пример взят прямо из книги.
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
Вот его заключительные аргументы:
Этот подход [...] более лаконичен, предоставляет механизм сериализации бесплатно и обеспечивает железную гарантию от множественных экземпляров, даже перед сложными атаками сериализации или отражения. Хотя этот подход еще не получил широкого распространения, одноэлементный тип перечисления является лучшим способом реализации синглтона .
На enum
постоянная единичная гарантия
Тип enum не имеет экземпляров, отличных от определенных его константами. Попытка явно создать экземпляр типа enum - это ошибка времени компиляции (§15.9.1).
Метод final clone
в Enum
гарантирует, что константы перечисления никогда не могут быть клонированы, а специальная обработка механизмом сериализации гарантирует, что повторяющиеся экземпляры никогда не будут созданы в результате десериализации. Рефлексивная реализация типов перечислений запрещена. Вместе эти четыре вещи гарантируют, что экземпляров типа enum не существует, кроме тех, которые определены константами enum.
При отложенной инициализации
Следующий фрагмент:
public class LazyElvis {
enum Elvis {
THE_ONE;
Elvis() {
System.out.println("I'M STILL ALIVE!!!");
}
}
public static void main(String[] args) {
System.out.println("La-dee-daaa...");
System.out.println(Elvis.THE_ONE);
}
}
Создает следующий вывод:
La-dee-daaa...
I'M STILL ALIVE!!!
THE_ONE
Как видите, константа THE_ONE
не создается в конструкторе до тех пор, пока к ней не обращаются в первый раз.