How to Implement Singleton Design Pattern in Java (Step-by-Step)
What is singleton design pattern
A Singleton Pattern says that just “define a class that has only one instance and provides a global point of access to it . If singleton class is loaded by two classloaders, two instance of singleton class will be created, one for each classloaders.
Key Concepts
- Only one object is created
- Global access to that object
- Object is controlled by the class itself

1. Significance of Serialization in Singleton Pattern
Serialization in Java means converting an object into a byte stream so it can be:
- Saved to a file
- Sent over a network
- Stored in a database
Deserialization is the reverse process (byte stream → object). Even if your class ensures only one instance, deserialization creates a NEW object, which violates the Singleton rule.
Example: Singleton Class (Without Protection)
- Singleton.java
import java.io.Serializable;
class Singleton implements Serializable {
private static final long serialVersionUID = 1L;
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
2.TestSingleton.java
import java.io.*;
public class TestSingleton {
public static void main(String[] args) throws Exception {
Singleton instance1 = Singleton.getInstance();
// Serialize
ObjectOutput out = new ObjectOutputStream(new FileOutputStream("rkdigital.ser"));
out.writeObject(instance1);
out.close();
// Deserialize
ObjectInput in = new ObjectInputStream(new FileInputStream("rkdigital.ser"));
Singleton instance2 = (Singleton) in.readObject();
in.close();
// Compare instances
System.out.println(instance1 == instance2);
}
}
output
false // false that means Singleton is broken
Why This Happens?
During deserialization:
- JVM does NOT use your constructor
- It creates a new object from byte stream
To resolve this issue, you need to override the readResolve() method that enforces the singleton. It is called just after the object is deserialized. It returns the singleton object.
- Singleton.java
import java.io.Serializable;
class Singleton implements Serializable {
private static final long serialVersionUID = 1L;
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
// Prevents new object creation during deserialization
protected Object readResolve() {
return instance;
}
}
2. TestSingleton.java
import java.io.*;
public class TestSingleton {
public static void main(String[] args) throws Exception {
Singleton instance1 = Singleton.getInstance();
// Serialize
ObjectOutput out = new ObjectOutputStream(new FileOutputStream("rkdigital.ser"));
out.writeObject(instance1);
out.close();
// Deserialize
ObjectInput in = new ObjectInputStream(new FileInputStream("rkdigital.ser"));
Singleton instance2 = (Singleton) in.readObject();
in.close();
// Compare instances
System.out.println(instance1 == instance2);
}
}
Output :
ture
2.Inheritance of Singleton Class
Inheriting a singleton class should be prohibited. Making a singleton class inheritable means any number of child classes can inherit from it creating multiple instances of the singleton class which will obviously violate the principle of singletons.
If you allow inheritance:
- Each subclass can create its own instance
- This breaks the “single instance” rule
Example : Singleton class with Inheritance
- Singleton.java
class Singleton {
protected static Singleton instance;
protected Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2. ChildSingleton.java
class ChildSingleton extends Singleton {
private static ChildSingleton childInstance;
private ChildSingleton() {}
public static ChildSingleton getInstance() {
if (childInstance == null) {
childInstance = new ChildSingleton();
}
return childInstance;
}
}
3. SingletonTest.java
public class SingletonTest {
public static void main(String[] args) {
Singleton parent = Singleton.getInstance();
ChildSingleton child = ChildSingleton.getInstance();
System.out.println(parent == child);
}
}
output :
false // false means Singleton is broken across hierarchy
To address the above issues, please follow the steps outlined below.
- Make class final
- Private constructor
3. Cloning in singleton
Cloning is a concept to create duplicate objects. Using clone we can create copy of object. Suppose, we create clone of a singleton object, then it will create a copy that is there are two instances of a singleton class, hence the class is no more singleton.
- Singleton.java
class Singleton implements Cloneable {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // ❌ creates new object
}
}
2. Test.java
public class Test {
public static void main(String[] args) throws Exception {
Singleton obj1 = Singleton.getInstance();
Singleton obj2 = (Singleton) obj1.clone();
System.out.println(obj1 == obj2); // false
}
}
clone()creates a new instance in memory- It bypasses the Singleton control logic
To overcome this issue, override clone() method and throw an exception from clone method that is CloneNotSupportedException. Now whenever user will try to create clone of singleton object, it will throw exception and hence our class remains singleton .
class Singleton implements Cloneable {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException(“Cloning not allowed in Singleton”);
}
}
4.Reflection in Singleton Pattern
Inspecting and modifying classes, constructors, methods, and fields at runtime, even if they are private. Reflection can call a private constructor and create a new object, This breaks the Singleton guarantee.
- Singleton.java
class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
2. Test.java
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
Singleton instance1 = Singleton.getInstance()
// Using reflection to break Singleton
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true); // bypass private
Singleton instance2 = constructor.newInstance();
System.out.println(instance1 == instance2);
}
}
output :
false //Singleton is broken
- Reflection bypasses
privateconstructor - JVM allows forced object creation
To overcome the above issues , add protection in constructor.
class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
if (instance != null) {
throw new RuntimeException("Use getInstance() method");
}
}
public static Singleton getInstance() {
return instance;
}
}