2013-09-24 10 views
32

Kto może wyjaśnić, co się dzieje?Blokada statyczna nie jest wywoływana

public class MagicFinal { 

    public static void main(String[] args) { 
     System.out.println(A.s); 
    } 
} 

class A { 
    static { 
     System.out.println("class has been loaded"); 
    } 

    public static final String s = "final"; 

    public static final Integer i = 3; 


} 

konsoli:

końcowy

Co to jest? Nie rozumiem, dlaczego klasa nie została załadowana, wiem, że klasy zawsze ładują się przy pierwszym wywołaniu. Pole s jest w puli ciągów, widzę, że ostateczny modyfikator jest magiczny.

Jeśli usunę ostateczny modyfikator (public static String s = "final") będę się

konsoli:

klasa została załadowana

ostateczną

Uwaga: Zmieniłem pola i: public static final int i = 3; i pokaż go w conso le. Dostałem to samo, co w sytuacji String. Czemu?

Odpowiedz

46

"final" jest literałem literowym i jako taki jest compile-time constant expression. Wartość zmiennej static final zainicjowanej za pomocą wyrażenia stałego w czasie kompilacji jest bezpośrednio zakodowana w klasie, która się do niej odwołuje, i nie odwołuje się do klasy początkowej. Dlatego inicjalizacja klasy początkowej nie występuje.

Jako punkt bocznej, należy zwrócić uwagę na rozróżnienie między klasą loading i klasa inicjalizacji: Tylko ten ostatni jest występowanie jest precyzyjnie określony przez JLS. Ładowanie klasy może się zdarzyć w dowolnym momencie.

+1

Dobrze, dziękuję! A co z int ?? publiczny statyczny finał int i = 3; // nie zapisano klasy został załadowany public static final Integer i = 3; // klasa zapisu została załadowana – idmitriev

+4

Proszę przeczytać definicję wyrażenia stałego w czasie kompilacji, do którego podłączyłem w mojej odpowiedzi. 'int' jest wartością pierwotną,' String' jest jedynym przypadkiem specjalnej wartości referencyjnej, która może być zaangażowana w wyrażenie stałe, a 'Integer' nie jest ani. –

+0

@marko - Czy mówisz mi, że klasa A w ogóle się nie ładuje ?? czy jest to przypadek leniwego inicjowania? – TheLostMind

3

To jest napisane w Specyfikacji Języka Java {8.3.2.1 Inicjatory Zmiennych Klasy}. To musi odpowiedzieć na pytanie

One subtelności tutaj jest to, że w czasie wykonywania, zmienne statyczne, które są ostateczne i że są inicjowane z kompilacji wartości stałe są inicjowane jako pierwszy. To również dotyczy takich pól w interfejsach (§9.3.1). Zmienne te są "stałymi", które nigdy nie będą miały domyślnych wartości początkowych (§ 4.12.5), nawet przez przebiegłe programy . Więcej informacji można znaleźć w §12.4.2 i §13.4.9.

+0

Wydaje się, że masz na myśli * Specyfikacja języka Java, wydanie trzecie *. Nie ma takiego akapitu w * Specyfikacji językowej Java® Java SE 7 Edition *. – johnchen902

+0

Tak. To prawda. Sprawdzałem stare wydanie, ale stwierdzenie to jest dobre także dla JLS 7. Poniżej linii są od JLS7 W czasie działania, najpierw są inicjowane statyczne pola, które są inicjowane ze stałymi wyrażeń (§15.28) (§12.4.2). Dotyczy to również takich pól w interfejsach (§9.3.1). Te pola są "stałymi", które nigdy nie będą przestrzegane, aby mieć domyślne wartości początkowe (§ 4.12.5), nawet przez przebiegłe programy (13.4.9). –