Singleton via enum sposób jest Lazy inicjalizacji?
Jest to bardzo szeroko rozpowszechniony kod enum singleton:
public enum enumClazz{
INSTANCE
enumClazz(){
//do something
}
}
I kilka miejsc mówiło, że to leniwa inicjalizacja. Ale jestem zdezorientowany po przeczytaniu rozdziału 7 ' Inside The Java Virtual Machine ' -- the Lifetime of a Type:
Specyfikacja maszyny wirtualnej Java daje implementacje elastyczność w czasie ładowania i łączenia klas i interfejsów, ale ściśle określa Czas inicjalizacji. Wszystkie wdrożenia musi zainicjować każdy klasy lub interfejsu przy pierwszym aktywnym użyciu. Na następujące sześć sytuacji kwalifikuje się jako aktywne zastosowania:
- tworzona jest nowa instancja klasy (w bajtodach wykonanie nowej instrukcji. Alternatywnie, poprzez niejawne tworzenie, odbicie, klonowanie lub deserializacja.)
W przeciwieństwie do innych metod, które nie są używane przez klasy, nie są używane przez klasy, które nie są używane przez klasy.]}- użycie lub przypisanie pola statycznego zadeklarowanego przez klasy lub interfejsu, z wyjątkiem pól statycznych, które są ostateczne i zainicjalizowane przez wyrażenie stałej czasowej kompilacji (w bytekodach wykonanie Instrukcja getstatic lub putstatic)
- wywołanie pewnych refleksyjnych metod w Java API, takich jak metody w klasie Class lub w klasach w java.lang.reflect pakiet
- inicjalizacja podklasy klasy (Inicjalizacja klasy wymaga uprzedniej inicjalizacji jej klasy nadrzędnej.)
Po uruchomieniu Wirtualnej Maszyny Java, Klasa ta jest oznaczana jako klasa początkowa (z metodą main ()
Trzeci punkt z pogrubionym stylem wyjaśnia, że jeśli pole jest static final
, inicjalizacja pola następuje w czasie kompilacji. Podobnie, INSTANCE
w enumClazz
jest w domyśle równe public static final
i zgodne z punktem trzecim.
2 answers
enum
pola instancji są , a nie "zainicjalizowane wyrażeniem stałej czasowej kompilacji". Oni
nie może być, ponieważ tylko String
i typy prymitywne są możliwymi typami dla wyrażenia stałej czasowej kompilacji .
Oznacza to, że klasa zostanie zainicjowana, gdy INSTANCE
zostanie po raz pierwszy uzyskana (co jest dokładnie pożądanym efektem).
Wyjątek w pogrubionym tekście powyżej istnieje, ponieważ te stałe (static final
pola zainicjalizowane stałą czasu kompilacji wyrażenie) będzie skutecznie inlinowane podczas kompilacji:
class A {
public static final String FOO = "foo";
static {
System.out.println("initializing A");
}
}
class B {
public static void main(String[] args) {
System.out.println(A.FOO);
}
}
Wykonywanie klasy B
w tym przykładzie spowoduje Nie zainicjalizowanie A
(i Nie wypisanie "inicjalizacja a"). Jeśli spojrzysz w kod bajtowy wygenerowany dla B
zobaczysz literał Łańcuchowy o wartości "foo" i nie ma odniesienia do klasy A
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-17 15:33:03
Trzeci punkt z pogrubionym stylem wyjaśnia, że jeśli pole jest "static final", inicjalizacja pola następuje w czasie kompilacji
Nie do końca-dotyczy tylko " statycznych pól, które są ostateczne i zainicjowane wyrażeniem stałej czasu kompilacji":
static final String = "abc"; //compile time constant
static final Object = new Object(); //initialised at runtime
W Twoim przypadku singleton zostanie zainicjowany po załadowaniu klasy enum, tzn. po raz pierwszy enumClazz
jest odwołany w Twoim kodzie.
Więc jest skutecznie leniwy, chyba, że masz w kodzie jakieś oświadczenie, które używa enum.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-13 16:05:19