2017-01-20 30 views
2

我按照此post创建一个线程安全单例类,但INSTANCE中存在编译错误。它说The blank final field INSTANCE may not have been initialized。我的要求是我希望INSTANCE为空,程序记录此错误并尝试再次初始化此对象。如果仍然失败,程序退出。空白最终字段INSTANCE可能未被初始化

public class ServiceConnection { 
    private static class SingletonObjectFactoryHolder{ 
     private static final ServiceSoapBindingStub INSTANCE; 
     static 
     { 
      try { 
       INSTANCE = new ServiceSoapBindingStub(); 

      } catch (AxisFault e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace();    
      } 
     } 
    } 

    public static ServiceSoapBindingStub getInstance() { 
     return SingletonObjectFactoryHolder.INSTANCE; 
    } 
} 

但如果我使用如下代码,另一个错误:The final field INSTANCE may already have been assigned

public class ServiceConnection { 
    private static class SingletonObjectFactoryHolder{ 
     private static final ServiceSoapBindingStub INSTANCE; 
     static 
     { 
      try { 
       INSTANCE = new ServiceSoapBindingStub(); 

      } catch (AxisFault e) { 
       INSTANCE = null; 
       e.printStackTrace();    
      } 
     } 
    } 

    public static ServiceSoapBindingStub getInstance() { 
     return SingletonObjectFactoryHolder.INSTANCE; 
    } 
} 

但如果我使用如下代码没有错误弹出。

public class ServiceConnection { 
    private static class SingletonObjectFactoryHolder{ 
     private static final ServiceSoapBindingStub INSTANCE; 
     static 
     { 
      try { 
       INSTANCE = new ServiceSoapBindingStub(); 

      } catch (AxisFault e) { 
       e.printStackTrace(); 
       throw new RuntimeException();      
      } 
     } 
    } 

    public static ServiceSoapBindingStub getInstance() { 
     return SingletonObjectFactoryHolder.INSTANCE; 
    } 
} 

为什么会发生这种情况?

+1

嗯,是的......你看到TODO?做到这一点:)如果存在“AxisFault”,您希望发生什么?目前,您不会将任何内容分配给“INSTANCE”...也许您应该抛出一个'RuntimeException'封装'e'?无论如何,你基本上已经被洗净...... –

+0

错误“空白最终字段INSTANCE可能未被初始化”只是声明你没有初始化字段INSTANCE ... _private static final ServiceSoapBindingStub INSTANCE = null; _应该摆脱这个信息。当然,乔恩有一个观点,你需要通过一切手段改善你的代码。 –

+0

这将删除错误消息,但不会出现错误。 –

回答

2

鉴于你所说的,你不应该为此使用类初始化。特别是:

  • 你想尝试多次
  • 您想使用checked异常

。这都是可行的,但是你需要初始化移动到getInstance方法:

public class ServiceConnection { 
    private static final Object lock = new Object(); 
    private static ServiceSoapBindingStub instance; 

    public static ServiceSoapBindingStub getInstance() throws AxisFault { 
     // Note: you could use double-checked locking here if you really 
     // wanted. 
     synchronized (lock) { 
      if (instance == null) { 
       instance = new ServiceSoapBindingStub(); 
      } 
      return instance; 
     } 
    } 
} 

(您可以捕获该异常登录,然后重新抛出,当然 - 但考虑是否更高级别将反正登录吧)