Careeroza
Singleton
One Instance Only
Singleton ensures a class has exactly one instance and gives global access to it — for config, a connection pool or a cache. Three common implementations:
Example
public class Main {
public static void main(String[] args) {
System.out.println(AppConfig.INSTANCE.get("currency"));
System.out.println("Same enum instance: " + (AppConfig.INSTANCE == AppConfig.valueOf("INSTANCE")));
System.out.println("Same holder instance: " + (IdGenerator.getInstance() == IdGenerator.getInstance()));
System.out.println(IdGenerator.getInstance().next() + ", " + IdGenerator.getInstance().next());
System.out.println("Same DCL instance: " + (Registry.getInstance() == Registry.getInstance()));
}
}
// 1. Enum singleton: simplest, thread-safe, safe against reflection and serialization (Effective Java's choice)
enum AppConfig {
INSTANCE;
private final java.util.Map<String, String> values = java.util.Map.of("currency", "INR");
String get(String key) { return values.get(key); }
}
// 2. Initialization-on-demand holder: lazy and thread-safe thanks to class loading rules
class IdGenerator {
private int counter = 1000;
private IdGenerator() {}
private static class Holder { static final IdGenerator INSTANCE = new IdGenerator(); }
static IdGenerator getInstance() { return Holder.INSTANCE; }
synchronized int next() { return ++counter; }
}
// 3. Double-checked locking: needs volatile
class Registry {
private static volatile Registry instance;
private Registry() {}
static Registry getInstance() {
if (instance == null) {
synchronized (Registry.class) {
if (instance == null) instance = new Registry();
}
}
return instance;
}
}Output
INR Same enum instance: true Same holder instance: true 1001, 1002 Same DCL instance: true
In Practice
Note: Singletons are global state and make testing harder. In Spring you rarely write one: every @Service/@Component bean is a singleton by default, managed by the container and injected where needed.