Singleton:在构造函数中抛出异常

时间:2013-05-27 16:19:40

标签: java reflection singleton

为了防止使用反射破坏Singleton,一种方法是在私有构造函数中抛出异常,如下面的代码所示:

public final class Foo {

    private static final Foo INSTANCE = new Foo();

    private Foo() {
        if (INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return INSTANCE;
    }
}

以上是标准代码,但我在想的是它是线程安全的吗?如果多个线程尝试同时使用反射创建实例[即在主内存中加载类之前,暗示实例将为null]那么它们会成功吗?

2 个答案:

答案 0 :(得分:1)

在加载之前,您无法访问类的静态成员(无论是直接还是通过反射)。静态最终成员在加载过程中初始化(step 9 of the JLS description)。

所以在你的情况下,线程无法做到:

  • 在正确构建之前,请参阅INSTANCE
  • INSTANCE视为null(除非第一次调用new Foo()引发异常)
  • 初始化第二个实例(除非该代码依赖于a different class loader

答案 1 :(得分:0)

创建反射安全单例的最佳方法是使用枚举。 It is described here