Browse Java Design Patterns & Enterprise Application Architecture

Implementing Singleton in Java

Implement Singleton in Java deliberately, with clear lifecycle, thread-safety, and testability boundaries.

Singleton: A pattern that guarantees one accessible instance of a type within a process and gives controlled global access to it.

The key word is controlled. In Java, a Singleton is not automatically good design just because the implementation is technically correct. The real question is whether the system truly benefits from one shared instance or whether the pattern is being used as disguised global state.

The Smallest Valid Shape

A basic eager singleton is simple:

1public final class AppConfig {
2    private static final AppConfig INSTANCE = new AppConfig();
3
4    private AppConfig() {}
5
6    public static AppConfig getInstance() {
7        return INSTANCE;
8    }
9}

This works because construction happens once during class initialization. There is no lazy logic and no race condition around creation.

Main Implementation Options

A leaf page about implementing Singleton should still show the main choices clearly:

VariantGood fitMain caveat
Eager static fieldCheap startup-owned instancePays construction cost whether used or not
Synchronized accessorSimple code with infrequent accessLocks on every access path
Initialization-on-demand holderLazy creation with good claritySlightly less obvious to readers unfamiliar with the idiom
Double-checked lockingRare cases needing lazy init with explicit controlHigher complexity and easier to get wrong
Enum singletonSerialization-safe, process-wide singleton with minimal ceremonyAwkward when lazy parameters or subclass-like variation matter

For deeper detail, see:

A Strong Lazy Default

When Java teams truly need lazy initialization and want to avoid unnecessary synchronization overhead, the holder idiom is usually a strong option:

 1public final class MetricsRegistry {
 2    private MetricsRegistry() {}
 3
 4    private static final class Holder {
 5        private static final MetricsRegistry INSTANCE = new MetricsRegistry();
 6    }
 7
 8    public static MetricsRegistry getInstance() {
 9        return Holder.INSTANCE;
10    }
11}

This relies on class initialization guarantees instead of manual locking logic.

The Real Design Questions

Before choosing Singleton, ask:

  • Is there truly one instance per JVM process?
  • Does shared access improve correctness, or just convenience?
  • How will tests isolate or reset the state?
  • Should this resource instead be owned by a DI container or application bootstrap layer?

Those questions matter more than the mechanics of private constructors.

When It Still Makes Sense

Singleton can be reasonable for:

  • one process-wide metrics registry
  • a tightly controlled cache manager
  • one configuration object created at startup
  • a resource coordinator that is truly singular in the application model

Even then, the state inside the singleton should be reviewed carefully. A singleton full of mutable runtime state is often where hidden coupling begins.

Hazards You Should Not Ignore

The implementation choice is only part of the story. Java singleton code also needs to survive surrounding language features.

Common hazards:

  • serialization creating another logical instance
  • reflection bypassing constructor assumptions
  • cloning or copy-like APIs undermining uniqueness
  • test isolation problems caused by mutable static state

This is why singleton implementation pages should not stop at “private constructor plus static accessor.” For a focused treatment of those edges, see Serialization Issues with Singleton.

What Makes It Dangerous

The pattern becomes harmful when:

  • callers reach for it from anywhere instead of receiving dependencies explicitly
  • tests become order-dependent because global state leaks between runs
  • initialization timing becomes unpredictable
  • it is used as a shortcut around actual wiring or lifecycle design

The most common Java singleton bug is not thread safety anymore. It is architectural laziness.

Prefer The Smallest Possible Global Surface

If a singleton is justified, keep its public surface small and its responsibilities narrow. It should not become a service locator, configuration bag, or miscellaneous object registry.

Design Review Questions

When reviewing a Java singleton, ask:

  • Why exactly must there be one instance?
  • Which implementation variant matches the lifecycle need best?
  • How will tests control or replace it?
  • Would explicit dependency injection express this boundary more honestly?

Singleton is valid when singularity is part of the model. It is a smell when singularity is only a convenience story.

Loading quiz…
Revised on Thursday, April 23, 2026