The blank final field INSTANCE may not have been initialized

I follow this post to create a thread safe singleton classs, but there is an compile error in INSTANCE. It said The blank final field INSTANCE may not have been initialized. My requirement is I want INSTANCE is null and the program log this error and try init this object again. If still fail, the program exit.

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

But If I use the Code as follows, another error: 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;
    }   
} 

But If I use the Code as follows no error pop up.

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

Why this happens?

Jon Skeet
people
quotationmark

Given what you've said, you shouldn't be using class initialization for this. In particular:

  • You want to try multiple times
  • You want to use a checked exception

Both of those are feasible, but you'll need to move the initialization into the getInstance method:

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

(You can catch the exception to log it and then rethrow, of course - but consider whether a higher level would be logging it anyway.)

people

See more on this question at Stackoverflow