Singleton in Java

What is Singleton?

Singleton is simply a class that is instantiated exactly once.

How to create Singleton in Java?

Following are broadly three different ways in which we can create Singleton in Java.

  1. Private constructor and public static final field
  2. Private constructor and public static factory method
  3. Enum with one element

1. Private constructor and public static field

//Singleton with private constructor and public static final field
public class Singleton{
	
	//Create Instance of the Class and make it as final, so that later on it cannot be changed
	public static final Singleton INSTANCE = new Singleton();
	
	//Make constructor private, so that it can be instantiated only from inside of the class 
	private Singleton(){
		//Throw exception if someone tries to instantiate the object by accessing the constructor using reflection
		if(INSTANCE != null){
			//Instance is not null, means already one instance of the class is created, hence throw execption.
			throw new RuntimeException("Class should be instantiated only once, don't try to be smart");
		}
	}
	
	/**
	 * Other code of the class goes here
	 * /
}

The private constructor is called only during initialization of the INSTANCE variable and since INSTANCE variable is final, it can not be assigned to something else.

NOTE: It is not enough to make constructor private, since a privileged client can invoke private constructor of the class using reflection and set it’s accessible proerty to true using setAccessible(true) and then create new instances, this will create more than one instance of the class and thus it won’t be singleton anymore. This is shown in the below code snippet

Singleton instance = Singleton.INSTANCE;
//Get list of constructor for this class
Constructor[] constructors =  Singleton.class.getDeclaredConstructors();
for(Constructor constructor : constructors){
	//setAccessible to true, this will now allow code to invoke the private Constructor
	constructor.setAccessible(true);
	
	//If the constuctor does not throw exception for second instantiation,
	//then below code will create new instance of the calss and sysout will return false
	Singleton newInstance = (Singleton)constructor.newInstance();
	System.out.println("New instance is equal to instance? " + (newInstance == instance));
}

To prevent this throw exception from the constructor, if it is making the second instance of the class

 

2. Private constructor and public static factory method

//Singleton with private constructor and public static final field
public class Singleton{
	
	//Create Instance of the Class and make it as final, so that later on it cannot be changed
	private static final Singleton INSTANCE = new Singleton();
	
	//Make constructor private, so that it can be instantiated only from inside of the class 
	private Singleton(){
		//Throw exception if someone tries to instantiate the object by accessing the constructor using reflection
		if(INSTANCE != null){
			//Instance is not null, means already one instance of the class is created, hence throw execption.
			throw new RuntimeException("Class should be instantiated only once, don't try to be smart");
		}
	}
	
	//Provide public static factory method
	public static Singleton getInstance(){
		return INSTANCE;
	}
	
	/**
	 * Other code of the class goes here
	 * /
}

Here again, the private constructor is called only during initialization of the INSTANCE variable and since INSTANCE variable is final, it can not be assigned to something else.

But it has the same caveat as of the approach 1, and private constructor should throw exception if it is being called to instantiate object more than once.

3. Enum with one element

//Singleton using Enum with one field -- preferred approach
public enum Singleton{
	INSTANCE;

	/**
    * Other code of the class goes here
	**/
}

Third and recommended approach of creating Singleton is with the Java ENUM. It provides guarantee against multiple instantiation and against reflection / serialization attacks.

 
 

Singleton and Serialization of object

If Singleton created using method 1 & 2 above, implements Serializable then it should declare all instance fields as transient and provide implementation for readResolve() method. If fields are not declared transient, then each time serialize instance is deserialized a new instance will be created.

Following readResolve() method can be added for deserialization of the objects

// readResolve method to preserve singleton property
private Object readResolve() {
	// Return the Singleton instance and let the garbage collector take care of its impersonator.
	return INSTANCE;
}

NOTE: 3rd approach mentioned above(Enum with one element) does not suffer from the serialization issue mentioned above and it is the recommended approach to implement the Singleton

 
 

Singleton and object Clone

If Singleton class does not extend any Class, then there is no need to worry about the cloning. Because default clone method will throw CloneNotSupportedException

But if class extends any class, then there is one caveat that if parent class implements Cloneable, then multiple instance of the Singleton class can be created. To prevent this implement following clone method

//throw exception on cloning
public Object clone() throws CloneNotSupportedException {
	throw new CloneNotSupportedException(); 
}

NOTE: Approach 3 mentioned above does not suffer from this cloning caveat and it is the preferred method for implementing Singleton
 
 

What is the difference between Java Singleton object and Spring Singleton bean?

Java Singleton is unique for the JVM, whereas Spring Singleton bean is unique for container. There could be multiple Spring container inside the same JVM, and in that each container will have its own Singleton bean, thus multiple instance of the Singleton inside JVM and hence different from the Java Singleton.