Why enum singleton is lazy?

后端 未结 2 814
后悔当初
后悔当初 2021-01-23 13:39

I saw answers like these, tried to clarify via comments, and was unsatisfied by examples here.

Maybe it\'s time for this specific question...

Why enum singleton im

2条回答
  •  悲&欢浪女
    2021-01-23 14:35

    May I wager the following:

    You are trying to identify 2 "processes" or ... "things" (let's make this easy to understand - because if I start saying "Code Blocks", it sounds more difficult)...

    • At some point the class-loader will run, and you would like to know what "things" will be executed when the class-loader loads a class.
    • At another point invoking a method on the class will cause another "thing" to run / execute, and you would like to know which, exactly, (which "processes") would start..

    The following facts are relevant:

    • Static initializers are run when the class-loader loads the class. The class-loader will not load the class until the code that is running encounters the need to load it (because a method or field has been invoked) such as: touchClass()
    • If a singleton instance of EITHER a class, OR an enumerated type has a field that is being initialized in the static part of the class it will be loaded as soon as you 'touch' the class - because the Class-Loader runs all static initializations for a class or enum on loading.
    • Lazy loading, likely, (And this is my "interpretation" about what you are asking) would happen when a method invokation asks the class to create a singleton instance - which could happen quite a bit of time after the "loading" of the class or enum.

    A class like the following:

    public class LazySingleton
    {
        // At time of class-loading, this singleton is set to 'null'
        private static singleton = null;
    
        // This is a method that will not be invoked until it is called by
        // some other code-block (some other "thing")...  When "touchClass()"
        // is called, the singleton instance is not created.
        public static LazySingleton retrieveSingleton()
        {
            if (singleton == null) singleton = new LazySingleton();
            return singleton;
        }
    
        // DOES NOTHING...  The Singleton is *not* loaded, even though the
        // Class Loader has already loaded this Java ".class" file
        // into memory.
        public static void touchClass() { }
    
        private LazySingleton()
        { System.out.println("constructing: LazySingleton"); }
    }
    

    Here on the other hand:

    public enum EagerEnum
    {
      // The class loader will run this constructor as soon as this 'enum'
      // is loaded from a '.class' file (in JAR or on disk) into memory
      MyEnumConstant();
    
      private EagerEnum()
      { System.out.println("Eager Enum Constructed"); }
    
      // This will cause the Class Loader to Load this enum from the
      // Java ".class" File immediately, and the "MyEnumConstant" will
      // also have to be loaded - meaning the constructor will be called.
      public static void touchEnum() { }
    }
    

    So the following code would produce the output

    LazySingleton.touchClass();            // Prints nothing
    EagerEnum.touchClass();                // Prints "Eager Enum Constructed"
    LazySingleton.getSingletonInstance();  // Prints "constructing: LazySingleton
    

提交回复
热议问题