Singleton类的实现可以像下面这样简单:
public class MyClass {
private final static MyClass myClass = new MyClass();
private MyClass() {}
public static MyClass getInstance() {
return myClass;
}
}
结束:
public class MyClass {
private final static MyClass myClass;
private MyClass() {}
public static MyClass getInstance() {
if(null == myClass) {
myClass = new MyClass();
}
return myClass;
}
}
上述实施中哪个更好&为什么呢?
我观察到的一件事是对于第一个实现,对象构造函数在静态块之前被调用(如果有的话)。
此外,如果第二个实现的线程安全版本(可能是双重空检查和同步块),这应该是首选吗?
答案 0 :(得分:1)
是。你可以使用第一个版本,但我建议你使用enum
。维基百科在Singleton
上的条目说
在他的书 Effective Java 的第二版中,Joshua Bloch声称 a single-element enum type is the best way to implement a singleton 支持任何支持枚举的Java。
像
这样的东西public enum Singleton {
INSTANCE;
}
答案 1 :(得分:1)
yoy需要注意定义单例类的原则规则是:
这取决于您的需求,是否需要提前初始化或延迟初始化。第一个是早期初始化的示例,而第二个是延迟初始化的示例。有多种方法可以定义完美的Singleton类
答案 2 :(得分:1)
我想对单身设计模式有所了解。
您的第一个代码段
public class MyClass {
private final static MyClass myClass = new MyClass();
public static MyClass getInstance() {
return myClass;
}
}
上面的方法工作正常但有缺点,因为实例在实际需要之前就已经创建了很多,所以在运行时想到如果实例不大的情况,你可以保留它,如果它没有被使用但是如果它很大然后创建实例的目的是什么。这种方法称为Eager初始化
下面显示的代码表示第二种称为Lazy初始化的方法 公共类MyClass {
private final static MyClass myClass;
public static MyClass getInstance() {
if(null == myClass) {
myClass = new MyClass();
}
return myClass;
}
}
但是在这里,你的代码还有一个缺点,让我们理解上面代码中的缺陷
让我们考虑我们有两个线程,即T1和T2,两个线程都用于创建实例并执行检查 null == myClass ,现在两个线程都已将实例变量识别为null,因此假设它们必须创建一个实例。它们按顺序进入同步块并创建实例。最后,我们的应用程序中有两个实例。
这可以通过简单的双重检查锁定来解决。下面的代码将向您展示更好的实现方式。请注意 - 我在代码中使用了私有构造函数。
public class MyClass {
private final static MyClass myClass = null;
//private constructor
private MyClass(){
}
public static MyClass getInstance() {
if(myClass == null) {
synchronized (MyClass.class){
// Double check
if(myClass == null){
myClass = new MyClass();
}
}
}
return myClass;
}
}