Enforce the singleton property with a private constructor or an enum type

What is singleton?

The singleton class is a class that has only one instance per JVM. The singleton class is to ensure that the same object is used by multiple threads.

Where do we use singleton class?

When we are designing a system that has system configurations, settings that should be the same across all threads in a JVM, then we should use a singleton class?

How to make a class singleton?

There are multiple approaches we can make a class singleton. Let us discuss different approaches to create a singleton class in a JVM.

Approach #1: Implement singleton with an Enum in Java

This is the best approach to make singleton in Java. If we try this approach then it is 100% guaranteed that only one instance of the singleton will be available in a JVM.

public enum MySingleton {
  INSTANCE;   
}

Approach #2: Implement singleton with public static final field

This approach is really neat and useful for creating a singleton. It is also simple and easy to use.

public class MySingleton {
  public static final MySingleton INSTANCE = new MySingleton();  
  private MySingleton() {} // private constructor
}

Disadvantages
1. We can not avoid writing private constructor in the class even though we are not doing anything inside of it. If we remove private constructor, then an implicit parameterless default constructor is created with the same access modifier as the class.

2. Static fields are initialized at class loading time. So, the Singleton instances are created even in a case we are not using them at runtime.

Approach #3: Implement singleton with public static factory method

In this approach, we can access the getInstance method to get an instance. As we have a static method, in the future if we decide the class to be not a singleton we can easily do that.

public class MySingleton {
    private static final MySingleton INSTANCE = new MySingleton();
    private MySingleton() {} // private constructor
    public static MySingleton getInstance(){
        return INSTANCE;
    }
}

Disadvantages
1. We can not avoid writing private constructor in the class even though we are not doing anything inside of it. If we remove private constructor, then an implicit parameterless default constructor is created with the same access modifier as the class.

2. Static fields are initialized at class loading time. So, the Singleton instances are created even in a case we are not using them at runtime.

Approach #4: Implement singleton with lazy instantiation

This approach does not create instance on class loading and synchronization makes the singleton.

public class MySingleton {
    private static MySingleton INSTANCE = null;
    private MySingleton() {} // private constructor
    public static MySingleton getInstance() {
        if (INSTANCE == null) {
            synchronized (MySingleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new MySingleton();
                }
            }
        }
        return INSTANCE;
    }
}

Disadvantages
1. We can not avoid writing private constructor in the class even though we are not doing anything inside of it. If we remove private constructor, then an implicit parameterless default constructor is created with the same access modifier as the class.

Frequently asked questions (FAQ)

Following are some questions about Java singleton:

How Enum instantiates and who does the new MySingleton?

Answer:
In the above case the following happens:

INSTANCE becomes:  public static final MySingleton INSTANCE = new MySingleton();

So we could re-write the above code:

public final class MySingleton {
    public final static MySingleton INSTANCE = new MySingleton();
    private MySingleton(){} 
}

Oracle resource about singleton.