Why enum singleton is lazy?

后端 未结 2 811
后悔当初
后悔当初 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条回答
  • The first two linked answers (by Peter Lawrey and Joachim Sauer) both agree that enums are not lazily initialized. Answers in the third link are simply wrong about what lazy initialization means.

    The recommendation to use enums as singletons originates from Josh Bloch's Effective Java. Notably, the chapter on enum singletons makes no mention of laziness. There is a later chapter dedicated to lazy initialization, that likewise makes no mention of enums. The chapter contains two highlights.

    • If you need to use lazy initialization for performance on a static field, use the lazy initialization holder class idiom.
    • If you need to use lazy initialization for performance on an instance field, use the double-check idiom.

    Undoubtedly, enums would be another idiom on this list if they were in any way lazily initialized. In fact they are not, although confusion about the meaning of lazy initialization results in some incorrect answers, as the OP shows.

    0 讨论(0)
  • 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
    
    0 讨论(0)
提交回复
热议问题