java 单例和异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2284502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:25:50  来源:igfitidea点击:

Singleton and Exception

javaexceptionsingleton

提问by CaptainHastings

Whats the best way to design a singleton class that could throw an exception?

设计可能引发异常的单例类的最佳方法是什么?

Here I have a Singleton (using Bill Pugh's method, documented in Wiki for Singleton).

在这里,我有一个单身人士(使用 Bill Pugh 的方法,在 Wiki 中记录在单身人士身上)。

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

If an exception is thrown at 2, I would like to propagate it to the caller. However, I can't throw an exception from line 1.

如果在 2 处抛出异常,我想将其传播给调用者。但是,我不能从第 1 行抛出异常。

So, is my only option to return a null object if the singleton object wasn't created correctly?

那么,如果未正确创建单例对象,我是返回空对象的唯一选择吗?

Thanks

谢谢

P.S I do realize that this Singleton can break if its loaded via different classloaders or if loaded reflexively, but it's good enough for my purpose.

PS 我确实意识到如果通过不同的类加载器加载或者反射加载,这个单例可能会中断,但它对我的目的来说已经足够了。

//UPDATE

//更新

I am curious, can I not rearrange my design as below to throw exceptions?

我很好奇,我可以不重新排列我的设计如下以抛出异常吗?

Also, I don't need any synchronization (the classloader guarantees that the static inner class will only loaded once and only when getInstance() is called). Thus, thread-safe and lazily-instantiated?

此外,我不需要任何同步(类加载器保证静态内部类只会加载一次,并且仅在调用 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();
 }

Thanks again.

再次感谢。

回答by BalusC

Use a static initializer and rethrow the Exceptionas ExceptionInInitializerError. Click the link to read the Javadoc, you'll see that it suits exactly for this particular functional requirement: handling exceptions during static initialization. A singleton is in fact nothing less or more than a statically and lazily initialized global object.

使用静态初始值设定项并重新抛出Exceptionas ExceptionInInitializerError。单击链接阅读 Javadoc,您将看到它完全适合这个特定的功能需求:在静态初始化期间处理异常。单例实际上就是一个静态且延迟初始化的全局对象。

private static class SingletonObjectFactoryHolder{
    private static final ObjectFactory INSTANCE;
    static {
        try {
            INSTANCE = new ObjectFactory();
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
}

No need for double checked lockingidiom which is considered an anti-pattern and in some circumstances even unsafe.

不需要双重检查锁定习惯用法,这被认为是一种反模式,在某些情况下甚至是不安全的。

回答by Roman

Just don't throw exception from object's constructor. You can provide init ()method and throw your exception from there if it's necessary.

只是不要从对象的构造函数中抛出异常。如果需要,您可以提供init ()方法并从那里抛出异常。

回答by Zac

You could check for null INSTANCE inside of getInstance, and lazily initialize it. But typically its best if constructors don't throw, if you can make the constructor safer that would probably be best.

您可以在 getInstance 中检查 null INSTANCE,并延迟初始化它。但通常最好是构造函数不抛出,如果你能让构造函数更安全那可能是最好的。

回答by Tom Neyland

I agree with Arne Burmeister, the code for that would look like:

我同意 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.
    }

}