skip to content

What is the Singleton pattern, and what are the common ways to implement it in Java?

level: juniorimportance: must knowfreq 75%

answer

  1. private constructor + static field + getInstance()
  2. eager / lazy / holder / enum
  3. holder = lazy + thread-safe, no lock
  4. enum = Bloch's best, attack-proof
  5. Runtime.getRuntime() is the JDK example

basics

~20 s

A Singleton ensures a class has exactly one instance and gives global access to it. In Java you hide the constructor (make it private) and expose one shared instance, either created eagerly in a static field or lazily in a getInstance() method.

solid answer

~50 s

A Singleton guarantees one instance of a class per JVM and a single global access point. The mechanics are always: a private constructor (so no one can call new), a static field holding the one instance, and a static accessor that returns it. Common idioms: (1) eager init - assign the instance in the static field directly, created at class load, simple and thread-safe; (2) lazy init - create it on first getInstance() call, which needs care to stay thread-safe; (3) the static holder idiom - a private nested class holds the instance, giving lazy + thread-safe with no locking; (4) the enum singleton - a single-constant enum, which Effective Java recommends because it is concise and immune to reflection and serialization attacks. A JDK example is Runtime.getRuntime(). The pattern is criticized for hidden global state and harder testing, so prefer dependency injection where you can.

go deeper

for a junior

Can state the intent (one instance, global access) and write the private-constructor + static-getInstance() form; recognizes Runtime.getRuntime().

for a middle

Distinguishes eager vs lazy and knows the naive lazy version is not thread-safe; can write the static-holder idiom and explain why it is lazy and safe.

for a senior

Picks the idiom deliberately (holder vs enum), articulates the testability/global-state downsides, and reaches for dependency injection instead of hard singletons where appropriate.

for a principal

Frames singletons as an application-scope/lifecycle concern, weighs container-managed single instances (Spring beans) vs language singletons, and sets team conventions around when a true singleton is justified.

## What problem does Singleton solve? Sometimes exactly one object should exist for a whole program: a configuration registry, a connection pool, a logging facility. The **Singleton pattern** (from the Gang of Four design-patterns book) ensures a class has **exactly one instance** and provides a **single global point of access** to it. ### The core mechanics Three ingredients appear in every Java singleton: 1. A **private constructor** - so outside code cannot write `new MyClass()`. (A constructor is the special method that builds an object; making it `private` means only the class itself can call it.) 2. A **static field** holding the one instance. (`static` means the field belongs to the class itself, not to any object - there is exactly one copy shared by everyone.) 3. A **static accessor** (conventionally `getInstance()`) that returns that one instance. ### Idiom 1 - Eager initialization ```java public final class Config { private static final Config INSTANCE = new Config(); private Config() {} public static Config getInstance() { return INSTANCE; } } ``` The instance is built when the class is **loaded** (the JVM loads a class the first time it is used). The JVM guarantees class initialization happens once and is thread-safe, so this is automatically safe across threads. The only downside: the object is created even if you never call `getInstance()`. For a cheap object that does not matter. ### Idiom 2 - Lazy initialization Build the instance only on the first `getInstance()` call (saves work if it is never used). A naive lazy version is **not thread-safe**: two threads could both see `null` and both create an instance. Making it safe requires either a `synchronized` accessor (correct but slow because every call locks) or the more advanced double-checked-locking idiom (covered in its own question). ### Idiom 3 - Static holder (initialization-on-demand holder) ```java public final class Config { private Config() {} private static class Holder { static final Config INSTANCE = new Config(); } public static Config getInstance() { return Holder.INSTANCE; } } ``` The nested `Holder` class is loaded only when `getInstance()` first touches `Holder.INSTANCE`. So creation is **lazy** (deferred to first use) and **thread-safe** (the JVM's once-only class-init guarantee), with **no locking** on the hot path. This is the recommended idiom for a class-based singleton. ### Idiom 4 - Enum singleton ```java public enum Config { INSTANCE; public void doWork() { /* ... */ } } ``` An `enum` with a single constant is a singleton: the JVM creates exactly one `INSTANCE`. *Effective Java* (Joshua Bloch) calls this the best way, because it is concise and the language itself blocks the usual attacks - you cannot reflectively call an enum constructor, and enum serialization is handled specially so you never get a second copy. ### A JDK example `Runtime.getRuntime()` returns the one `Runtime` object representing the running JVM - a real, eager singleton in the standard library. ### Why people criticize Singletons A singleton is **global mutable state**, which makes code harder to test (you cannot easily swap in a fake) and hides dependencies. Modern designs often prefer **dependency injection** - create one instance and pass it where needed - over a hard-coded singleton. Knowing the pattern is essential; using it everywhere is a smell.

  • Why does Effective Java recommend the enum singleton over a class with a private constructor?
    Because a single-element enum is concise, the JVM guarantees one instance, and the language itself blocks reflection (you cannot reflectively instantiate an enum) and provides correct serialization for free - so it is immune to the attacks that break class-based singletons.
  • Is Runtime.getRuntime() lazy or eager?
    Eager - the single Runtime instance is held in a static final field initialized when the Runtime class loads, so getRuntime() just returns the already-built object.

saying these in an interview costs you the question

  • Saying a singleton is just 'a static class' - a singleton is an object with a private constructor, not a class of static methods.
  • Claiming the naive lazy getInstance() is thread-safe - it is not.
  • Forgetting the private constructor, so callers can still write new.
  • Believing every shared service must be a Singleton; dependency injection is usually better.

context