Why is a single-element enum considered the best way to implement a singleton in Java?
answer
- enum X { INSTANCE; } — one constant = the singleton
- Class-init creates it once; JVM guarantees thread-safe init
- Reflection can't instantiate enums (IllegalArgumentException)
- Serialization name-based -> no second copy, no readResolve
- Can't extend a class; eager, no runtime ctor args
basics
~20 sBecause the JVM guarantees exactly one instance of each enum constant, and that single instance survives reflection and serialization attacks for free. So enum Singleton { INSTANCE; } gives you a thread-safe, attack-proof singleton with no boilerplate.
solid answer
~50 sThe enum singleton is `enum Singleton { INSTANCE; ... }` — INSTANCE is the one and only instance. It's preferred (Effective Java Item 3) because the language itself enforces single instantiation: enum constants are created once during class initialization, which the JVM guarantees is thread-safe, so there's no double-checked locking or volatile needed. It's also immune to the two classic ways other singletons are broken: reflection can't call an enum constructor (Constructor.newInstance throws IllegalArgumentException for enums), and serialization is name-based and returns the existing constant, so you can't deserialize a second copy — no readResolve needed. You add fields, methods, and behavior to the enum normally. The only real limitations are that an enum singleton can't extend a class (it already extends Enum) and the instance is eagerly created at class-load, so it's unsuitable when you need lazy initialization tied to runtime parameters.
code
java · 10 linespublic enum Registry {
INSTANCE;
private final Map<String, Object> store = new ConcurrentHashMap<>();
public void put(String k, Object v) { store.put(k, v); }
public Object get(String k) { return store.get(k); }
}
// usage
Registry.INSTANCE.put("db", dataSource);
Object db = Registry.INSTANCE.get("db");go deeper
Knows enum Singleton { INSTANCE; } gives one instance and is the recommended singleton form.
Explains it's thread-safe via class init and that you add fields/methods to INSTANCE normally.
Explains immunity to reflection and serialization attacks specifically, and the no-inheritance / eager-creation limitations.
Weighs the enum singleton against DI-managed singletons for testability and lifecycle, and knows when global mutable state via a singleton is itself a design smell.
## What a singleton is A **singleton** is a class designed to have exactly **one instance** for the whole program, reachable from a global access point. Classic uses: a configuration registry, a connection pool, a logging hub. ## How singletons are usually done — and how they break Traditional singletons use a `private` constructor plus a `static` instance: ```java public class Config { public static final Config INSTANCE = new Config(); private Config() {} } ``` Three classic attacks break this 'one instance' promise: 1. **Reflection** — `Constructor c = Config.class.getDeclaredConstructor(); c.setAccessible(true); c.newInstance();` bypasses `private` and makes a *second* object. 2. **Serialization** — if `Config implements Serializable`, deserializing creates a *new* object each time unless you add a `readResolve()` returning `INSTANCE`. 3. **Multithreaded lazy init** — lazy variants need careful double-checked locking with a `volatile` field, easy to get wrong (see unsafe publication). ## The enum singleton A **single-element enum** sidesteps all of this: ```java public enum Config { INSTANCE; private final Map<String,String> data = new HashMap<>(); public String get(String k) { return data.get(k); } } // use: Config.INSTANCE.get("port"); ``` Why it is the best implementation (Effective Java, Item 3): - **Single instance is language-guaranteed.** Enum constants are created **once**, during the enum's class initialization. The JVM guarantees class initialization is **thread-safe** (it holds the class's initialization lock), so `INSTANCE` is created exactly once with full memory visibility — **no `volatile`, no double-checked locking, no synchronization** to write or get wrong. - **Reflection-proof.** The reflection API **explicitly forbids** instantiating enums: `Constructor.newInstance` throws `IllegalArgumentException("Cannot reflectively create enum objects")`, and you cannot get an accessible enum constructor to call. So attack #1 is impossible. - **Serialization-proof for free.** Enum serialization is **name-based**: it writes the constant's name and resolves the existing constant via `valueOf` on read, returning the same `==` instance. No `readResolve` needed, and custom serialization hooks are ignored, so attack #2 is impossible. You still get a normal class: add **fields**, **methods**, even **constant-specific behavior**. `INSTANCE` is just a constant with state. ## Limitations / when not to use it - **No class inheritance.** The enum already extends `java.lang.Enum`, so an enum singleton **cannot `extends` another class** (it can still implement interfaces — useful for testing/mocking against an interface). - **Eager creation.** The instance is created when the enum class is initialized (first reference). If you need **lazy** initialization, or initialization that depends on **runtime constructor arguments**, an enum doesn't fit — use a holder-class idiom or a DI container instead. - **DI frameworks** often manage singletons themselves (one bean per context), which is usually a better fit for testability than a hard global; the enum singleton shines for genuinely global, parameterless singletons. ## One-line summary `enum Singleton { INSTANCE; }` is concise, **thread-safe by construction**, and **immune to reflection and serialization attacks** — the only mainstream singleton that is all three with zero boilerplate.
- How does the enum singleton avoid double-checked locking entirely?The constant is initialized during enum class initialization, and the JVM guarantees class init runs once under the class init lock with proper visibility. So you get safe, lazy-on-first-class-use, single creation without writing any synchronization.
- When is an enum singleton a poor choice?When you need lazy init driven by runtime constructor arguments, when the singleton must extend a concrete class, or when a DI container should own the lifecycle for testability. Then use the holder-class idiom or a managed bean.
A normal singleton is a 'one per customer' rule enforced by a sign on the door — people sneak in through windows (reflection) and back doors (serialization). The enum singleton is a building with literally one room baked into the blueprint: there's no second room to sneak into.
saying these in an interview costs you the question
- Adding readResolve to an enum singleton — unnecessary; serialization already returns the existing constant.
- Claiming the enum singleton needs volatile/synchronized for thread safety.
- Saying reflection can still create a second enum instance — newInstance throws for enums.
- Thinking an enum singleton can extend another class.