Lazy singleton initialization in java

We all know this old well-known idiom of lazy-init singleton:

public class Singleton {
    private static volatile Singleton instance;

    private Singleton()
    {
        // init...
    }

    public static Singleton getInstance()
    {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }

        return instance;
    }
}

However, the following idiom is also lazy, by nature, because the instance will be init only when the class is first accessed, handled by the class loader:

public class Singleton
{
    private static final Singleton instance = new Singleton();

    private Singleton()
    {
        // init..
    }

    public static Singleton getInstance()
    {
        return instance;
    }
}

So the question is, why would we want to use the first example and not the second? (not referring to the fact that it's better to use frameworks such as spring for managing your objects' life cycle..)

Even if you hold a reference to the singleton in another class, like this:

public class Holder {
   private int member1;
   private int member2;
   private Singleton myService = Singleton.getInstance();

}

The singleton will be created when the Holder class is loaded, regardless of which approach we take

Any insights? thanks

1 answer

  • answered 2018-01-11 19:48 Neil Locketz

    What about something like this?

    public class Singleton {
        ...
        public static int getSomeStaticInfo() { return 42; }
        ...
    } 
    
    public class Holder {
        private int member1;
        private int member2 = Singleton.getSomeStaticInfo();
        private Singleton myService;
    
        public void init() {
            myService = Singleton.getInstance();
        }
    }
    

    The behavior of when your singleton is initialized differs between the two versions. This is where version 1 exhibits the correct (in terms of what we'd want when we say "lazy") behavior. Just because you load the class, doesn't mean you want it initialized.