Domanda Ordine di inizializzazione statica di Java [duplicato]


Questa domanda ha già una risposta qui:

Sto cercando di scoprire l'ordine in cui avviene l'inizializzazione, o piuttosto la ragione alla base del perché l'inizializzazione si verifica in questo ordine. Dato il codice:

public class Main {

    {
        System.out.printf("NON-STATIC BLOCK\n");
    }

    static{
        System.out.printf("STATIC BLOCK\n");
    }

    public static Main m = new Main();

    public Main(){
        System.out.printf("MAIN CONSTRUCTOR\n");
    }

    public static void main(String... args) {
        //Main m = new Main();
        System.out.printf("MAIN METHOD\n");

    }
}

Produzione:

STATIC BLOCK

NON-STATIC BLOCK

MAIN CONSTRUCTOR

MAIN METHOD

Tuttavia, in movimento mLa dichiarazione precedente al blocco di inizializzazione produce:

NON-STATIC BLOCK

MAIN CONSTRUCTOR

STATIC BLOCK

MAIN METHOD

e non ho assolutamente idea del perché avvenga in questo ordine. Inoltre, se elimini il static parola chiave nella dichiarazione di m, né il blocco di init né il fuoco del costruttore. Qualcuno può aiutarmi con questo?


23
2017-09-27 19:36


origine


risposte:


Penso che ti manchi solo sezione 12.4.2 del JLS, che include:

Successivamente, eseguire gli inizializzatori delle variabili di classe e gli inizializzatori statici della classe, o gli inizializzatori di campo dell'interfaccia, in ordine testuale, come se fossero un singolo blocco.

La parte "in ordine testuale" è il bit importante.

Se cambi m da variabile statica a variabile di istanza, il campo non verrà inizializzato da classe inizializzazione: verrà inizializzato solo da esempio inizializzazione (ad esempio quando viene costruita un'istanza). Al momento, ciò causerà un overflow dello stack: la creazione di un'istanza richiede la creazione di un'altra istanza, che richiede la creazione di un'altra istanza, ecc.

EDIT: allo stesso modo sezione 12.5 specifica l'inizializzazione dell'istanza, inclusi questi passaggi:

  • Eseguire gli inizializzatori dell'istanza e gli inizializzatori delle variabili di istanza per questa classe, assegnando i valori degli inizializzatori delle variabili di istanza alle corrispondenti variabili di istanza, nell'ordine da sinistra a destra in cui appaiono testualmente nel codice sorgente della classe. Se l'esecuzione di uno di questi inizializzatori comporta un'eccezione, non vengono elaborati ulteriori inizializzatori e questa procedura viene completata improvvisamente con la stessa eccezione. Altrimenti, continuare con il passaggio 5.

  • Esegui il resto del corpo di questo costruttore. Se quell'esecuzione termina bruscamente, allora questa procedura si conclude bruscamente per lo stesso motivo. Altrimenti, questa procedura viene completata normalmente.

Ecco perché vedi "BLOCCO NON STATICO" prima di "MAIN CONSTRUCTOR".


28
2017-09-27 19:39