具有静态内部类和双重检查锁定的单例

时间:2015-12-29 14:06:08

标签: java design-patterns singleton

我正在阅读关于Singleton设计模式和评估不同的实现。我怀疑以下的实现:

:一种。使用静态内部类的单例实现

public class SingletonWithStaticClass {

private SingletonWithStaticClass(){}

private static class SingletonInnerClass{
    public static SingletonWithStaticClass INSTANCE = new SingletonWithStaticClass();

}

public static SingletonWithStaticClass getInstance(){
    return SingletonInnerClass.INSTANCE;
}

}

B中。单身双重检查锁定

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;
}

}

哪一个更好?

我觉得我们可以在第一个实现中使用Reflection访问私有构造函数,其中第二个实现是安全的(来自Reflection攻击)。

但是,我不打算在我的生产代码中使用任何这些,我将使用 枚举 。但是出于这两个,当考虑反射攻击时,是不是第一个实现被破坏?

如果我的理解错误,请纠正我。

2 个答案:

答案 0 :(得分:6)

两者都过于复杂。第一个是Java 5.0之前的最佳选择,但第二个从来都不是一个好选择。它在Java 5.0之前没有用,它需要一个volatile字段,在此版本之后你可以使用enum

我更喜欢使用enum来定义一个只有一个实例的类。它是一个final类,线程安全,延迟加载,并且有一个private构造函数。

enum Singleon {
    INSTANCE;
}

双锁定单例仅在必须在其构造中提供配置信息时才有用。在这种情况下,我更喜欢使用依赖注入来提供/配置单例,并且只有不需要配置的无状态单例。

答案 1 :(得分:1)

两者都不好 - 并且尝试使用不同的比例来比较它们会适得其反。

第一个是不必要的复杂,正如你所说的那样,反思黑客是开放的,但另一个也是如此,只是略微不那么明显。

第二个使用synchronized并附带费用。