Java Singleton Design Pattern: Guide with Best Practices and Examples
🎯 What Will You Learn in This Guide?
This guide explains in depth the Singleton pattern, which is among Java's Creational Design Patterns.
You will learn this pattern, which allows only a single instance of a class to be created, with different approaches and safe implementation methods.
🧠 Technical Summary
Purpose: To create only one instance throughout the application and provide global access to this instance.
Area of use: Logging, database connection, caching, thread pool management.
What you will learn:
- Singleton principles
- Eager, Static Block, Lazy and Thread-Safe approaches
- Bill Pugh method (recommended solution)
- Reflection and Serialization risks and ways to protect
🧩 Singleton Basics
For a class to be a Singleton:
- Private constructor → prevents creating new objects.
- Private static instance → stores a single instance.
- Public static access method → returns this instance to the outside world.
⚙️ 1. Early Initialization
The instance is created while the class is loaded.
public class EagerInitializedSingleton {
private static final EagerInitializedSingleton ornek = new EagerInitializedSingleton();
private EagerInitializedSingleton(){}
public static EagerInitializedSingleton getInstance() { return ornek; }
}
➡️ Simple but takes up space in memory even if it is not used.
⚙️ 2. Static Block Initialization
Similar to early startup, but provides error handling.
public class StaticBlockSingleton {
private static StaticBlockSingleton ornek;
private StaticBlockSingleton(){}
static {
try { ornek = new StaticBlockSingleton(); }
catch (Exception e) { throw new RuntimeException("Singleton hatası"); }
}
public static StaticBlockSingleton getInstance() { return ornek; }
}
➡️ Offers the advantage of exception handling, but still loads prematurely.
⚙️ 3. Lazy Initialization
The instance is created only when needed.
public class LazyInitializedSingleton {
private static LazyInitializedSingleton ornek;
private LazyInitializedSingleton(){}
public static LazyInitializedSingleton getInstance() {
if (ornek == null) ornek = new LazyInitializedSingleton();
return ornek;
}
}
➡️ Resource friendly but not safe in multi-thread environment.
⚙️ 4. Thread-Safe Singleton
Provides security in multi-threading with synchronization.
public static synchronized ThreadSafeSingleton getInstance() {
if (ornek == null) ornek = new ThreadSafeSingleton();
return ornek;
}
➡️ Thread-safe but performance cost is high.
🔄Double-Checked Locking
It only syncs during initial creation.
if (ornek == null) {
synchronized (ThreadSafeSingleton.class) {
if (ornek == null) ornek = new ThreadSafeSingleton();
}
}
➡️ Balances performance and security.
⚙️ 5. Bill Pugh Singleton (Safest Method)
It is the most efficient and safe method after Java 5.
public class BillPughSingleton {
private BillPughSingleton(){}
private static class Yardimci {
private static final BillPughSingleton ORNEK = new BillPughSingleton();
}
public static BillPughSingleton getInstance() { return Yardimci.ORNEK; }
}
➡️ Provides thread-safe and lazy loading without synchronization.
⚠️ 6. Breaking Singleton with Reflection
Reflection can access the private constructor and create a new object. To prevent this, the following check can be added to the constructor:
private Singleton() {
if (instance != null) throw new RuntimeException("Yalnızca bir örnek oluşturulabilir!");
}
➡️ Provides protection against reflection attack.
🟣 7. Enum Singleton
The safest solution suggested by Joshua Bloch:
public enum EnumSingleton {
ORNEK;
public void islemYap() { /* ... */ }
}
➡️ Immune to Reflection, JVM only produces one instance.
🧱 8. Serialization and readResolve()
Serialization can create new objects. To prevent this:
protected Object readResolve() { return getInstance(); }
➡️ The same instance is preserved after reverse serialization.
💬 Frequently Asked Questions (FAQ)
- What is the difference between singleton and static class?
Singleton is an object, not a static class; It can hold state.
- Why is Bill Pugh the best method?
Thread-safe, no lazy and no synchronization overhead.
- Why is readResolve() necessary?
It prevents the creation of new objects during deserialization.
- Where is singleton not used?
It reduces testability in multi-dependency (state-sharing) structures.
- Why is Enum Singleton preferred?
Provides natural protection against both Reflection and Serialization.
✅ Result
In this guide, you learned the Java Singleton design pattern with different implementation methods. Now you know which approach is suitable in terms of performance, security and flexibility.
🚀 Start your own Java project on GenixNode and test these patterns in a real environment.

