In Java gibt es einen einfachen Weg, einen Singleton bei Bedarf zu initialisieren (lazy), ohne Methoden mit synchronized deklarieren zu müssen. Dieses Entwurfsmuster ist als Initialization-On-Demand-Holder-Pattern bekannt geworden.
Beim Initialization-On-Demand-Holder-Pattern wird das Exemplar der Klasse als Klassenvariable einer statischen privaten inneren Klasse vorgehalten:
class MeinSingleton { private static class Holder { private static final MeinSingleton INSTANCE = new MeinSingleton(); } private MeinSingleton() {} public static MeinSingleton getInstance() { return Holder.INSTANCE; } }
Wie funktioniert dieses Konstrukt nun? Wenn die Klasse MeinSingleton initialisiert wird, werden ggf. alle Felder der Klasse initialisiert. Wenn Felder nur deklariert, aber nicht initialisiert werden, greift eine Standardinitialisierung: Objektreferenzen werden auf null gesetzt, primitive Typen werden mit Standardwerten wie “0″ initialisiert.
Statische Klassenvariablen werden bereits initialisiert, wenn die Klasse gelesen wird. Dies trifft auf die innere statische Klasse Holder jedoch nicht zu. Hier wird die Klassenvariable INSTANCE erst beim ersten Zugriff initialisiert – dies kann nur passieren, wenn die statische Methode getInstance() aufgerufen wird. Bei jedem folgenden Aufruf wird das korrekt initialisierte Exemplar der Klasse MeinSingleton zurückgegeben.
Näheres zur Initialisierung von Java-Klassen erfährt man in der Java Language Specification, Abschnitt 12.4.