Quando avviene l'inizializzazione della classe statica?


110

Quando vengono inizializzati i campi statici? Se non creo mai un'istanza di una classe, ma accedo a un campo statico, TUTTI i blocchi statici ei metodi statici privati ​​utilizzati per istanziare campi statici privati ​​vengono chiamati (in ordine) in quell'istante?

E se chiamo un metodo statico? Esegue anche tutti i blocchi statici? Prima del metodo?


Risposte:


156

L'inizializzazione statica di una classe avviene normalmente immediatamente prima della prima volta che si verifica uno dei seguenti eventi:

  • viene creata un'istanza della classe,
  • viene invocato un metodo statico della classe,
  • viene assegnato un campo statico della classe,
  • viene utilizzato un campo statico non costante, o
  • per una classe di primo livello, viene eseguita un'istruzione assert annidata lessicamente all'interno della classe 1 .

Vedere JLS 12.4.1 .

È anche possibile forzare l'inizializzazione di una classe (se non è già stata inizializzata) utilizzando Class.forName(fqn, true, classLoader)o la forma abbreviataClass.forName(fqn)


1 - L'ultimo punto elenco era presente nel JLS per Java 6 attraverso Java 8, ma apparentemente era un errore nella specifica. È stato finalmente corretto in Java 9 JLS: vedi sorgente .


9
C'è però una trappola comune. Le primitive Stringes sono sostituite e non referenziate. Se fai riferimento a una class Other { public static final int VAL = 10; }di una classe MyClass { private int = Other.VAL; }, la classe Othernon verrà caricata. Invece, il compilatore sostituirà semplicemente il campo finale in fase di compilazione.
Rafael Winterhalter

6
@RafaelWinterhalter - sì ... questo è il caso del campo statico costante .
Stephen C

2
@RafaelWinterhalter, questo non è vero per tutte le primitive o Stringvariabili "statiche finali" , solo per quelle inizializzate da un'espressione costante.
Lew Bloch

1
Sì, e il campo non ha nemmeno bisogno di essere staticmentre questo è un caso comune.
Rafael Winterhalter

1
È lo stesso linguaggio di programmazione. Sì.
Stephen C

14

I campi statici vengono inizializzati durante il inizializzazione "fase" di del caricamento della classe (caricamento, collegamento e inizializzazione) che include inizializzatori statici e inizializzazioni dei suoi campi statici. Gli inizializzatori statici vengono eseguiti in un ordine testuale come definito nella classe.

Considera l'esempio:

public class Test {

   static String sayHello()  {
      return a;
   }

   static String b = sayHello(); // a static method is called to assign value to b.
                                 // but its a has not been initialized yet.

   static String a = "hello";

   static String c = sayHello(); // assignes "hello" to variable c

    public static void main(String[] arg) throws Throwable {
         System.out.println(Test.b); // prints null
         System.out.println(Test.sayHello()); // prints "hello"
    }
}

Il Test.b viene stampato nullperché quando è sayHellostato chiamato nell'ambito statico, la variabile statica anon è stata inizializzata.


6
A rigor di termini, l'inizializzazione non è una "fase" di caricamento della classe. In effetti, alcune classi possono essere caricate ma mai inizializzate se l'applicazione non le utilizza effettivamente.
Stephen C

@Stephen C Hai ragione, l'ho usato per mancanza di un termine migliore, forse lo citerò.
naikus

@StephenC significa che mentre il caricamento della classe ha luogo, assegna memoria a variabili statiche (e metodi) ma quelle variabili statiche non sono inizializzate con i valori forniti nel codice? perché qui sembra che quando b-> sayHello () -> a, 'a' è in memoria ma il valore non è ancora assegnato.
Shabbir Essaji

Fondamentalmente sì.
Stephen C

1

Sì, tutti gli inizializzatori statici vengono eseguiti prima del primo accesso alla classe. Se fosse in un altro modo, lo definirei un bug.


Esistono modi per fare riferimento a una classe senza inizializzarla.
Lew Bloch
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.