Singleton lazy vs eager instantiation

With lazy initialization you crate instance only when its needed and not when the class is loaded. So you escape the unnecessary object creation. That being said there are other things to consider too. In lazy initialization you give a public API to get the instance. In multi-threaded environment it poses challenges to avoid unnecessary object creation. you put synchronization blocks which poses unnecessary locking to be done to check for object already created. So it becomes a performance issue in this case.

So if you are sure that creating you object is not going to take any significant memory and its almost always going to be used in your application then its good to create in static initialization. Also please do not forget to make your instance final in this case as it make sures that the object creation is reflected properly and in totality to main memory which is important in multi-threaded environment.

Please refer this tutorial from IBM on Singleton+ Lazy Loading+ Multithreaded Environment case

===============Edit on 09/09/2018====================

You should also look at object creation on demand pattern here.


You may call any other static methods or static member variable too to load the singleton instance.

class Logger {     
   private static Logger instance = new Logger(); 
   public static String LOG_LINE_SEPERATOR =  
      System.getProperty("line.separator");
   public static Logger getInstance() {  
          return instance;     
   } 

   public static String logPattern() {
       return null;
   }
} 

...

Logger.LOG_LINE_SEPERATOR; // load Logger instance or
Logger.logPattern(); // load Logger instance

For the reasons you mention, this is just a more complicated way of doing much the same as

enum Singleton {
    INSTANCE;
}

Using lazy initialisation is only useful if you are concerned that the class could be initilised but you don't want to load the singleton at that point. For most situations this is over kill.

Note: Just referencing the class does not initialise the class.

e.g. Say you have a badly written class which cannot be initilised until some condition is set. In this case n must be non-zero.

public class Main {
    public static void main(String ... args) {
        Class c= LazyLoaded.class;
        System.out.println(c);
    }

    static class LazyLoaded {
        static int n = 0;
        static {
            System.out.println("Inverse "+1000/n);
        }
    }
}

prints

class Main$LazyLoaded