Singleton Pattern in Java

Naveen AnamaneniUpdated · 5 min read

Some things should exist only once in a running program: the application's configuration, a connection pool, a cache of exchange rates. If every part of the code created its own, they'd waste memory and disagree with each other. The Singleton pattern makes a class guarantee that only one instance ever exists, and gives everyone a single way to reach it.

The Idea

One object, one way to reach it

Every singleton has the same three parts:

  1. A private constructor, so no one outside can call new.
  2. A static field holding the one instance.
  3. A static method (or field) that returns it.

Four Ways to Write One

Singletons.java▶ Try it
public class Singletons {
    static final class EagerConfig {
        private static final EagerConfig INSTANCE = new EagerConfig();
        private EagerConfig() { System.out.println("EagerConfig created"); }
        static EagerConfig getInstance() { return INSTANCE; }
    }
 
    static final class LazyConfig {
        private static LazyConfig instance;
        private LazyConfig() { System.out.println("LazyConfig created"); }
        static LazyConfig getInstance() {
            if (instance == null) {
                instance = new LazyConfig();
            }
            return instance;
        }
    }
 
    static final class HolderConfig {
        private HolderConfig() { System.out.println("HolderConfig created"); }
        private static class Holder {
            static final HolderConfig INSTANCE = new HolderConfig();
        }
        static HolderConfig getInstance() { return Holder.INSTANCE; }
    }
 
    enum AppSettings {
        INSTANCE;
        private String currency = "INR";
        String currency() { return currency; }
    }
 
    public static void main(String[] args) {
        System.out.println("Program started");
        EagerConfig e1 = EagerConfig.getInstance();
        System.out.println(e1 == EagerConfig.getInstance());
        LazyConfig l1 = LazyConfig.getInstance();
        System.out.println(l1 == LazyConfig.getInstance());
        HolderConfig h1 = HolderConfig.getInstance();
        System.out.println(h1 == HolderConfig.getInstance());
        System.out.println(AppSettings.INSTANCE.currency());
    }
}
Output
Program started
EagerConfig created
true
LazyConfig created
true
HolderConfig created
true
INR

How it works

  1. Eager: the instance is created when the class loads (here, at the first getInstance() call). Simple and thread-safe, because class loading is thread-safe.
  2. Lazy: created on the first call. This simple version is not thread-safe: two threads could both see null and create two objects. The thread-safe versions (synchronized and double-checked locking) come with the multithreading lessons, later in the course.
  3. Holder (initialization-on-demand): the nested Holder class loads only when getInstance() first touches it. Lazy and thread-safe, with no locking.
  4. Enum: an enum with one constant. The JVM guarantees exactly one instance, thread-safely, even against reflection and serialization.

Each true confirms that two calls return the same object, and each "created" line prints only once.

Comparing the Approaches

ApproachLazy?Thread-safe?Safe from reflection and serialization?
Eager static fieldNo (created at class load)YesNo
Lazy with null checkYesNoNo
Holder idiomYesYesNo
EnumNo (created at class load)YesYes

Reflection can call a private constructor and create a second object of a class-based singleton. With an enum, the JVM refuses:

Trying reflection on an enum singleton
java.lang.IllegalArgumentException: Cannot reflectively create enum objects

Common Mistakes

The unsynchronized lazy version in multithreaded code. Two instances can be created; use the holder idiom or an enum.

Forgetting the private constructor. Then anyone can call new and there's no singleton.

Using singletons for everything. Most classes need many instances or none; a singleton is the exception.

Interview Corner

How do you create a singleton in Java?

Make the constructor private, keep the single instance in a static field, and return it from a static method. It can be created eagerly in a static final field, lazily inside the accessor, or lazily and thread-safely with a private static holder class. The simplest robust approach is an enum with a single constant, which is thread-safe and can't be duplicated through reflection or serialization.

Why is the enum singleton considered the best?

The JVM guarantees that each enum constant is created exactly once, thread-safely during class initialization. Reflection can't create enum instances, and Java serialization preserves enum identity, so neither can produce a second copy. It also needs the least code.

Practice

  1. Easy: Write an eager singleton Counter with an increment() method, call it from two places, and show they share the count.
  2. Harder: Rewrite Counter as an enum singleton, and explain one advantage and one drawback compared with passing a Counter object into the classes that need it.

Quick check: Singleton

4 questions
1Which is essential for a singleton class?
2Which version is NOT thread-safe?
3Which singleton can't be broken with reflection?
4When is the holder idiom's instance created?

Key Takeaways

Was this tutorial helpful?

Lesson 180 of 482