设计可能引发异常的单例类的最佳方法是什么?
这里我有一个Singleton(使用Bill Pugh的方法,记录在Wiki for Singleton中)。
private static class SingletonObjectFactoryHolder{
//1
private static final ObjectFactory INSTANCE = new ObjectFactory();
}
private ObjectFactory() throws Exception{
//2
//create the factory
}
public static ObjectFactory getInstance(){
//3
return SingletonObjectFactoryHolder.INSTANCE;
}
如果在2处抛出异常,我想将其传播给调用者。 但是,我不能从第1行抛出异常。
那么,如果没有正确创建单例对象,我唯一的选择是返回一个空对象吗?
由于
P.S我确实意识到如果这个Singleton通过不同的类加载器加载或者如果被反射加载就会破坏,但它对我的目的来说已经足够了。
//更新
我很好奇,我可以不重新安排我的设计,如下所示抛出异常吗?
另外,我不需要任何同步(类加载器保证静态内部类只加载一次,并且仅在调用getInstance()时)。因此,线程安全和懒惰实例化?
private static class SingletonObjectFactoryHolder{
//1
public static ObjectFactory getInstance() throws Exception{
return new ObjectFactory();
}
}
private ObjectFactory() throws Exception{
//2
//create the factory
}
public static ObjectFactory getInstance(){
//3
return SingletonObjectFactoryHolder.getInstance();
}
再次感谢。
答案 0 :(得分:34)
使用静态初始化程序并将Exception
重新抛出为ExceptionInInitializerError
。单击链接以阅读Javadoc,您将看到它完全适合此特定功能要求:在静态初始化期间处理异常。事实上,单身实体不仅仅是一个静态和懒惰的初始化全局对象。
private static class SingletonObjectFactoryHolder{
private static final ObjectFactory INSTANCE;
static {
try {
INSTANCE = new ObjectFactory();
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
}
不需要被认为是反模式的double checked locking成语,在某些情况下甚至不安全。
答案 1 :(得分:0)
只是不要从对象的构造函数中抛出异常。如果有必要,您可以提供init ()
方法并从那里抛出异常。
答案 2 :(得分:0)
你可以在getInstance中检查null INSTANCE,然后懒洋洋地初始化它。但通常情况下,如果你可以使构造函数更安全,那么构造函数不会抛出它是最好的。
答案 3 :(得分:-1)
我同意Arne Burmeister,其代码如下:
private static class SingletonObjectFactoryHolder
{
private static ObjectFactory INSTANCE;
private ObjectFactory()
{
}
public static String getInstance() throws Exception
{
return (INSTANCE == null) ? (INSTANCE = new ObjectFactory()) : INSTANCE;
// A ternary operator might not be the best fit if you need to throw an exception, but I think it looks nicer than the if(INSTANCE==null){} else{} for lazy instantiation.
}
}