I've been wondering about singletons in Java. By convention, a singleton is set up something like this:
private static MyClass instance = null;
public static MyClass getInstance(){
if (instance == null){
instance = new MyClass();
}
return instance;
}
private MyClass(){}
Recently I've switched to using the following:
public static final MyClass instance = new MyClass();
private MyClass(){}
This is a lot shorter, faster as there's no null-check, and typing MyClass.instance
feels nicer to me than typing MyClass.getInstance()
. Is there any reason why the second is not the mainstream way to do this?
I can think of two reasons:
The first is Encapsulation: you might have second thoughts about how and when your singleton is initialized, after your class has been exposed to client code. And an initialization method gives you more freedom as to changing your strategy later on. For example you might change your mind and decide to use two different constructors instead of one, according to another static variable's value at runtime. With your solution you're bound to using just one constructor at the time your class is loaded into memory, whereas with
getInstance()
you can change the initialization logic without affecting the interface to the client code.The second is Lazy Initialization : with the conventional singleton implementation the
MyClass
object is loaded into memory only when needed by the client code for the first time. And if the client code doesn't need it at all, you save on the memory allocated by your application. Note that whether your singleton is needed or not might not be certain until the program runs. For example it might depend on the user interaction with the program.However the Lazy Initialization is not something you might necessarily want. For example if you're programming an interactive system and the initialization of your singleton is time consuming, it might actually be better to initialize it when the program is loading rather than when the user is already interacting with it, cause the latter might cause a latency in your system response the first time
getInstance()
is called. But in this case you can just have your instance initialized with the public method as in:The first version creates the instance the first time it is actually needed, while the second (the shorter) runs the constructor as soon as the class is initialized
The initialization upon first usage is a performance improvement that may speed up the startup of the application if the code in the constructor makes expensive operations. On the other hand, the second version is straightforward to read and is automatically thread-safe.
Anyway, the state of the art is not creating singleton in either ways: for a bunch of KB you can get dependency injection libraries that make it working for you, and also handle more complex scenarios (for example look at Spring and AOP-backed injection).
Note: the first version is not thread safe in the pasted snippet
Reflection: Reflection can be caused to destroy singleton property of singleton class, as shown in following example:
The best way to synchronize the threads is using Double Checked (to ensure that only one thread will enter the synchronized block at a time and to avoid obtaining the lock every time the code is executed).
The way you have first described is known as lazy instantiation, i.e the object will only be created when it is first called. This method is not thread-safe as it is possible for a second thread to create a second instance.
If you read the following book:
He explains that the best implementation of the singleton pattern is through the use of an
Enum
:Then you would call your singleton through the
Enum
as follows:This fits nicely with what you are saying in terms of it looks nicer and shorter to write but also guarantees there can never be a second instance.