[java] Perché i campi statici non sono inizializzati in tempo?



Answers

Proviamo un modo diverso per spiegare questo ...

Questa è la sequenza in cui passa la JVM quando si fa riferimento per la prima volta alla classe MyClass .

  1. Carica il codice byte in memoria.
  2. La memoria per la memoria statica viene cancellata (zero binario).
  3. Inizializza la classe:
    1. Esegui ogni inizializzatore statico nell'ordine in cui appare, questo include variabili static { ... } e blocchi static { ... } .
    2. JVM quindi inizializza la variabile statica myClass in una nuova istanza di MyClass .
    3. Quando ciò accade, la JVM nota che MyClass è già stato caricato (codice byte) e nel processo di inizializzazione , quindi ignora l'inizializzazione.
    4. Assegna memoria su heap per oggetto.
    5. Esegui costruttore.
    6. Stampa il valore di obj che è ancora null (poiché non fa parte delle variabili inizializzate dell'heap e del costruttore).
    7. Al termine del costruttore, eseguire il successivo inizializzatore statico che imposta obj su una nuova istanza di Object .
  4. Inizializzazione della classe eseguita. Da questo punto, tutte le chiamate del costruttore si comporteranno come si presume / si aspetti - cioè obj non sarebbe null ma un riferimento a un'istanza Object .

Ricorda che Java specifica che una variabile final viene assegnata un valore una volta. Non è che sia garantito che venga assegnato un valore quando il codice lo fa riferimento a meno che non si accerti che il codice lo faccia riferimento dopo che è stato assegnato.

Questo non è un bug. Questo è il modo definito per gestire l'utilizzo della classe durante la sua inizializzazione. Se così non fosse, allora la JVM andrebbe in un loop infinito. Vedere il passo # 3.3 (se la JVM non salta l'inizializzazione per una classe che è in fase di inizializzazione, dovrebbe semplicemente inizializzarla - ciclo infinito).

Nota bene, tutto ciò avviene sullo stesso thread che fa riferimento per primo alla classe. In secondo luogo, la JVM garantisce che l'inizializzazione verrà completata prima che qualsiasi altro thread possa utilizzare questa classe.

Question

Il seguente codice stampa null una volta.

class MyClass {
   private static MyClass myClass = new MyClass();
   private static final Object obj = new Object();
   public MyClass() {
      System.out.println(obj);
   }
   public static void main(String[] args) {}
}

Perché gli oggetti statici non vengono inizializzati prima dell'esecuzione del costruttore?

Aggiornare

Avevo appena copiato questo programma di esempio senza attenzione, pensavo che stessimo parlando di 2 campi Oggetto, ora ho visto che il primo è un campo MyClass ..: /




questo perché i campi statici sono inizializzati nello stesso ordine in cui sono definiti.




Related