I am reading about Singleton design pattern and evaluating different implementations. I have doubt with the below implementations:
A. Singleton Implementation with static inner class
public class SingletonWithStaticClass {
private SingletonWithStaticClass(){}
private static class SingletonInnerClass{
public static SingletonWithStaticClass INSTANCE = new SingletonWithStaticClass();
}
public static SingletonWithStaticClass getInstance(){
return SingletonInnerClass.INSTANCE;
}
}
B. Singleton double checked locking
public class SingletonWithDoubleCheck {
private static SingletonWithDoubleCheck INSTANCE = null;
private SingletonWithDoubleCheck(){
if(INSTANCE != null){
throw new RuntimeException("Accessing private constructor is prohibited. Use getInstance method instead");
}
}
public static SingletonWithDoubleCheck getInstance(){
if(INSTANCE == null){
synchronized (SingletonWithDoubleCheck.class) {
if(INSTANCE == null){
INSTANCE = new SingletonWithDoubleCheck();
}
}
}
return INSTANCE;
}
}
Which one is better?
I feel we can access the private constructor with Reflection in first implementation where as second implementation is safe (From Reflection attack).
However, I am not going to use any of these in my production code, I will use enum instead. But out of these two, isn't the first implementation is broken when considered Reflection attack?
Please correct me if my understanding is wrong.
Both are overly complicated. The first was the best option before Java 5.0, however the second was never a good option. It didn't work before Java 5.0, it requires a volatile
field and after this version you could use enum
I prefer using an enum
to define a class with exactly one instance. It is a final
class, thread safe, lazy loaded, and has a private
constructor.
enum Singleon {
INSTANCE;
}
The double locking singleton is only useful if you must provide configuration information in it's construction. In this case, I prefer to use Dependency Injection to provide/configure singletons and only have stateless Singletons which don't require configuration.
Neither are good - and attempting to compare them using different scales is counter-productive.
The first is unnecessarily complex and, as you say, is open to reflection hacking, but so is the other one, just slightly less so.
The second uses a synchronized
which comes with a cost.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With