What is a Singleton class and how do you create one in Java?
The Singleton pattern ensures that a class has exactly one instance throughout the application's lifetime and provides a global point of access to it. It is one of the Gang of Four creational patterns.
There are several implementation approaches, each with different thread-safety and laziness characteristics.
**Eager initialization**: The instance is created when the class loads. Simple and thread-safe because class loading is atomic. Drawback: the instance is created even if never used. ```java public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; } } ```
**Double-checked locking** (lazy, thread-safe): Delays creation until first use. The `volatile` keyword is essential — without it, the JVM may reorder instructions and a second thread can observe a partially initialized object. ```java private static volatile Singleton instance; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) instance = new Singleton(); } } return instance; } ```
**Initialization-on-demand holder** (Bill Pugh): Leverages class loader guarantees. The nested static class is not loaded until `getInstance()` is called. Thread-safe without synchronization overhead. ```java private static class Holder { static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; } ```
**Enum singleton** (Joshua Bloch's recommendation): Inherently serialization-safe and reflection-proof. Enum instances are guaranteed single by the JVM. ```java public enum Singleton { INSTANCE; } ```
Enums are preferred when you need guaranteed single-instance semantics with zero risk of serialization or reflection bypass.
Presents a correct thread-safe implementation and explains why naive lazy initialization without volatile or synchronization is broken.
Covers at least three implementation approaches, explains the volatile requirement in DCL, the class-loading guarantee in the holder pattern, and the enum approach's serialization safety.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment