为了防止使用反射破坏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]那么它们会成功吗?
答案 0 :(得分:1)
在加载之前,您无法访问类的静态成员(无论是直接还是通过反射)。静态最终成员在加载过程中初始化(step 9 of the JLS description)。
所以在你的情况下,线程无法做到:
INSTANCE
。INSTANCE
视为null(除非第一次调用new Foo()
引发异常)答案 1 :(得分:0)
创建反射安全单例的最佳方法是使用枚举。 It is described here