Neden enum singleton tembeldir?

Sep 24 2020

Bunun gibi cevaplar gördüm , yorumlarla açıklamaya çalıştım ve buradaki örneklerden memnun kalmadım .

Belki de bu özel sorunun zamanı gelmiştir ...

Numaralandırma singleton uygulamasına neden tembel denir ?

public enum EnumLazySingleton {
    INSTANCE;
    EnumLazySingleton() {
        System.out.println("constructing: " + this);
    }
    public static void touchClass() {}
}

İstekli uygulamadan farkı nedir?

public class BasicEagerSingleton {
    private static final BasicEagerSingleton instance = new BasicEagerSingleton();
    public static BasicEagerSingleton getInstance() {
        return instance;
    }
    private BasicEagerSingleton() {
        System.out.println("constructing: " + this);
    }
    public static void touchClass() {}
}

Her ikisi de erişmeden örnek olarak başlayacaktır INSTANCE/getInstance()- örneğin çağrı touchClass().

public class TestSingleton {
    public static void main(String... args) {
        System.out.println("sleeping for 5 sec...");
        System.out.println("touching " + BasicEagerSingleton.class.getSimpleName());
        BasicEagerSingleton.touchClass();
        System.out.println("touching " + EnumLazySingleton.class.getSimpleName());
        EnumLazySingleton.touchClass();
    }
}

Çıktı:

sleeping for 5 sec...
touching BasicEagerSingleton
constructing: BasicEagerSingleton@7bfcd12c
touching EnumLazySingleton
constructing: INSTANCE

Şimdi ikisinin de tembel olduğunu söyleyebiliriz . O zaman hevesli olan nedir ?

"İki kez kontrol edilmiş kilitleme" yolunun aslında ne kadar (örneğin) tembel (ve dağınık ve yavaş) olduğu açıktır. Ancak enum tembelse, kaçınılmaz sınıf yüklemesi nedeniyle herhangi bir singleton tembeldir - aslında her şey tembeldir. Bu ayrım hangi noktada bir anlam ifade etmeyecek?

Yanıtlar

3 jaco0646 Sep 24 2020 at 19:58

(İlk iki bağlantılı cevaplar Peter Lawrey ve Joachim Sauer ikisi) çeteleler kabul edersiniz değil tembel başlatıldı. Üçüncü bağlantıdaki yanıtlar, tembel başlatmanın ne anlama geldiği konusunda tamamen yanlıştır.

Numaralandırmaları tekil olarak kullanma önerisi Josh Bloch'un Etkili Java'sından gelmektedir. Bilhassa, enum singletons ile ilgili bölüm tembellikten hiç bahsetmiyor. Tembel başlatmaya adanmış daha sonraki bir bölüm var, bu da aynı şekilde numaralandırmalardan bahsetmiyor. Bölüm, iki önemli noktayı içerir.

  • Statik bir alanda performans için tembel başlatma kullanmanız gerekiyorsa, tembel başlatma tutucu sınıfı deyimini kullanın.
  • Bir örnek alanında performans için tembel başlatma kullanmanız gerekiyorsa, çift kontrol deyimini kullanın.

Şüphesiz, numaralandırmalar herhangi bir şekilde tembel olarak başlatılmış olsalardı bu listedeki başka bir deyim olurdu. Aslında değiller, ancak OP'nin gösterdiği gibi, tembel başlatmanın anlamı hakkındaki kafa karışıklığı bazı yanlış yanıtlara yol açsa da.

Y2020-09 Sep 24 2020 at 18:58

Aşağıdakilere bahse girebilir miyim:

2 "süreç" veya ... "things"(bunu anlamayı kolaylaştıralım - çünkü "Kod Blokları" demeye başlarsam kulağa daha zor geliyor) ...

  • Bir noktada sınıf yükleyici çalışacaktır "things"ve sınıf yükleyici bir sınıfı yüklediğinde neyin yürütüleceğini bilmek istersiniz .
  • Başka bir noktada, sınıftaki bir yöntemi çağırmak bir başkasının "thing"çalışmasına / yürütülmesine neden olur ve tam olarak hangisinin (hangisinin "processes") başlayacağını bilmek istersiniz ..

Aşağıdaki gerçekler önemlidir:

  • Statik başlatıcılar, sınıf yükleyici sınıfı yüklediğinde çalıştırılır. Sınıf yükleyici, çalışan kod onu yükleme ihtiyacıyla karşılaşana kadar sınıfı yüklemeyecektir (çünkü bir yöntem veya alan çağrılmıştır), örneğin:touchClass()
  • Bir tekil örneği ise ya bir sınıf, YA bir sayılan tip bir etti fieldbaşlatılmış edildiğini staticbunun yüklenecek sınıfın bir parçası olan en kısa sürede size 'dokunma' sınıfına - Sınıf-Yükleyici çalıştığı için tüm static initializationsbir sınıf için veya yükleme hakkında enum.
  • - Geç yükleme, muhtemelen, bir yöntemi invokation bir tekil örneğini oluşturmak için sınıf sorduğunda olur (Ve bu ne soran hakkında benim "yorumlama" dır) arasında "yükleme" sonra zaman biraz olabilirdi classveya enum.

Aşağıdaki gibi bir sınıf:

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

Öte yandan burada:

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() { }
}

Dolayısıyla aşağıdaki kod çıktıyı üretecektir

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