2012-11-25 26 views
7

Eventuali duplicati:
Java static class initialization
in what order are static blocks and static variables in a class executed?ordine di inizializzazione variabile statica, Java

Quando eseguo questo codice la risposta è 1, ho pensato che sarebbe stato 2. Quali è l'ordine di inizializzazione e il valore di k in ogni passo?

public class Test { 

static {k = 2;} 
static int k = 1; 

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

Modifica 1: come seguito a "k è impostato sul valore predefinito", quindi perché questo codice successivo non viene compilato? C'è un errore "Impossibile fare riferimento a un campo prima che sia definito".

public class Test { 

static {System.out.println(k);} 
static int k=1; 

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

Edit 2: Per qualche sconosciuto per me motivo^funziona quando al posto di "k" suo "Test.k".

Grazie per tutte le risposte. questo sarà sufficiente: D

+1

Per prima cosa, a k verrà assegnato il valore predefinito, quindi dall'alto verrà eseguito il codice statico e verranno assegnati 2, quindi verrà assegnato 1. Quindi viene chiamata la funzione principale e stampata k. 'static int k = 1' è effettivamente' static int k; 'dichiarazione, quindi' static {k = 1; } ' – nhahtdh

+0

@KennyTM Sì, se l'avessi eseguito nel modo in cui in quel post si incolla, vorrei sapere che cosa sta succedendo. – Hoto

+0

@nhahtdh Sarà assegnato il valore predefinito k? Allora perché questo codice non comiple: public class Test { \t \t statica {System.out.println (k); k = 2;} \t static int k; \t \t void main (String [] args) {public static \t \t System.out.println (k); \t} } – Hoto

risposta

7

Sono eseguiti nell'ordine in cui li si scrive. Se il codice è:

public class Test { 

    static int k = 1; 
    static {k = 2;} 

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

} 

allora l'uscita diventa 2.

L'ordine di inizializzazione è: ..the class variable initializers and static initializers of the class..., in textual order, as though they were a single block.

E i valori (per il codice) sono: k = 0 (default), allora è impostato su 2, poi è arretrato a 1.

è possibile verificare che in realtà è impostato su 2 eseguendo il seguente codice:

private static class Test { 

    static { 
     System.out.println(Test.k); 
     k = 2; 
     System.out.println(Test.k); 
     } 
    static int k = 1; 

    public static void main(String[] args) { 
     System.out.println(k); 
    } 
} 
+0

Non è quello che intendevo nella mia domanda. Volevo l'ordine di inizializzazione e i valori di k in ogni fase. – Hoto

+0

Ok, ho aggiunto una spiegazione più dettagliata. – tibtof

+0

Sì ... ma ora c'è un po 'di caos nella risposta xD – Hoto

3

Risposta breve

Quando l'inizializzazione della classe inizia, k avrà valore iniziale di 0.

Il blocco statico (dato che precede l'assegnazione nella dichiarazione) viene quindi eseguita, e k sarà assegnato 2.

Quindi l'inizializzatore nella dichiarazione viene eseguito e k verrà assegnato 1.

lunga spiegazione

lasciarci usare this example, dal momento che il vostro esempio è un po 'semplice:

class TestInitOrder { 
    static { 
    System.out.println(TestInitOrder.stat1); 
    System.out.println(TestInitOrder.stat2); 
    System.out.println(TestInitOrder.str); 
    System.out.println(TestInitOrder.str2); 

    str = "something"; 

    System.out.println(TestInitOrder.str); 
    System.out.println(TestInitOrder.str2); 
    System.out.println(TestInitOrder.lazy); 
    System.out.println(TestInitOrder.second); 
    } 

    private static final int stat1 = 10; 
    static final String str2 = "sdfff"; 
    static String str = "crap"; 
    private static int stat2 = 19; 
    static final Second second = new Second(); 
    static final int lazy; 

    static { 
    lazy = 20; 
    } 

    static { 
    System.out.println(TestInitOrder.str2); 
    System.out.println(TestInitOrder.stat2); 
    System.out.println(TestInitOrder.str); 
    System.out.println(TestInitOrder.lazy); 
    System.out.println(TestInitOrder.second); 
    } 

    public static void main(String args[]) { 
    } 

} 

class Second { 
    public Second() { 
    System.out.println(TestInitOrder.second); 
    } 
} 

Secondo Java Language Specification, da section 4.12.5:

Ogni variabile in un programma di deve avere un valore prima che venga utilizzato il suo valore:

  • Ogni variabile di classe, variabile esempio, o un componente di matrice viene inizializzato con il valore predefinito quando viene creato

(I seguenti righe dalla specifica specificare il valore di default per tutti i tipi, fondamentalmente qualche forma di 0, come 0, 0.0d, null, false, ecc)

Così prima classe viene inizializzato (a causa di uno dei these reasons), le variabili terrà un valore iniziale.

Secondo il detailed initialization procedure (solo i passi interessanti sono citati qui, e sottolineatura mia):

6. [...] Poi, inizializzare le final variabili di classe e campi di interfacce i cui valori sono compile-timeespressioni costanti (§8.3.2.1, §9.3.1, §13.4.9, §15.28).

[...]

9. successiva, eseguire sia le inizializzatori classe variabili e inizializzatori statici della classe oi inizializzatori campo dell'interfaccia, in ordine testuale, come se fossero un unico blocco .

Guardiamo al punto 6, con le variabili 4 final di classe: stat1, str2, second, lazy.

Da 10 è un'espressione costante, e quindi è "sdfff", e causa l'ordine di esecuzione, non è possibile osservare il valore iniziale per str2 e stat1. Per fare un'osservazione, il primo che puoi fare è al punto 9.

Il caso di second dimostra che quando il lato destro non è un'espressione costante in fase di compilazione, quindi il suo valore iniziale è visibile.

Il caso di lazy è diverso, poiché l'assegnazione viene eseguita in blocco statico e quindi avviene nel passaggio 9, quindi è possibile osservare il suo valore iniziale. (Bene, il compilatore controlla attentamente che lazy sia assegnato esattamente una volta).


Dopo l'inizializzazione delle variabili di classe finali con fase di compilazione espressione costante viene l'esecuzione dei blocchi statici e il resto degli inizializzatori.

Come si può vedere dall'esempio, i blocchi statici e inizializzazione avviene secondo ordine testuale - dimostrata con l'uso di str variabile - viene prima stampato come null, quindi something, quindi crap.

+0

@EJP: Si noti che 2 condizioni 1) ** finale ** variabili di classe e 2) inizializzatore è costante in fase di compilazione che viene eseguita in passo 6. Nessuna contraddizione qui. Puoi anche controllare il programma su ideone. – nhahtdh

Problemi correlati