1

为了防止 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 ],那么它们会成功吗?

4

2 回答 2

1

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

所以在你的情况下,线程不可能:

  • INSTANCE在正确构建之前查看。
  • 视为INSTANCEnull(除非第一次调用new Foo()引发异常)
  • 初始化第二个实例(除非该代码依赖于不同的类加载器
于 2013-05-27T16:26:21.450 回答
0

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

于 2013-05-27T16:22:42.530 回答