2012-12-19 14 views
23

ho 2 classi:L'inizializzatore statico viene eseguito dopo il costruttore, perché?

di Classe A:

public class A { 
    static B b = new B(); 

    static { 
     System.out.println("A static block"); 
    } 

    public A() { 
     System.out.println("A constructor"); 
    } 
} 

Classe B:

public class B { 
    static { 
     System.out.println("B static block"); 
     new A(); 
    } 

    public B() { 
     System.out.println("B constructor"); 
    } 
} 

ho creare una classe principale che crea solo nuova A:

public class Main { 
    public static void main(String[] args) { 
     new A(); 
    } 
} 

Il l'output che ottengo è:

B static block 
A constructor 
B constructor 
A static block 
A constructor 

Come si può vedere, il costruttore di A viene richiamato prima del suo inizializzatore statico.

Capisco che abbia qualcosa a che fare con la dipendenza ciclica che ho creato ma ho avuto l'impressione che l'inizializzatore statico dovrebbe sempre essere eseguito prima del costruttore.

Qual è la ragione per questo (tecnicamente nell'implementazione di Java)?

Si consiglia di evitare tutti gli inizializzatori statici tutti insieme?

+0

Chiunque downvoted si prega di lasciare un commento –

+2

buona domanda in realtà +1 .. :) – PermGenError

+0

@AviramSegal alcune persone sono abituali di downvote .. non hanno mai letto l'intera domanda, leggendo la voce, hanno downvoting la domanda. – Ravi

risposta

23
static B b = new B(); 

è prima

static { 
    System.out.println("A static block"); 
} 

Così si richiede che l'istanza B essere inizializzato prima di stampare "A static block".

E inizializzare la classe B significa che è necessario creare un'istanza A. Quindi non c'è modo per "Un blocco statico" per essere stampato prima che l'istanza A sia costruita.

Sì, l'inizializzazione statica di A è avviata prima che il costruttore venga avviato ma, a parte lo stallo, non ci sarebbe altra soluzione alla sequenza richiesta.

nota l'avviso in the specification:

Perché il linguaggio di programmazione Java è multithreaded, l'inizializzazione di una classe o interfaccia richiede un'attenta sincronizzazione, dal momento che qualche altro filo può tentare di inizializzare la stessa classe o di interfaccia allo stesso tempo. Esiste inoltre la possibilità che l'inizializzazione di una classe o un'interfaccia possa essere richiesta in modo ricorsivo come parte dell'inizializzazione di tale classe o interfaccia; ad esempio, una variabile inizializzatore in classe A potrebbe richiamare un metodo di una classe B non correlata, che a sua volta potrebbe richiamare un metodo di classe A. L'attuazione macchina virtuale Java è responsabile per prendersi cura di sincronizzazione e l'inizializzazione ricorsiva utilizzando la procedura seguente [doc continua con la procedura completa]

Una procedura, in Java come in altri linguaggi, è fondamentalmente per evitare le dipendenze cicliche in quanto la loro risoluzione potrebbe essere molto difficile da prevedere.

+1

Vorrei capire un errore, ma perché consentire questo comportamento incoerente? inoltre, non ho potuto trovare la documentazione per quello –

+0

ok, ho perso la specifica, grazie! –

Problemi correlati