2015-10-20 18 views
6

Beh, ho un tale codice:Quando vengono caricate le classi?

public class Main { 
    public static void main(String[] args) { 
     Test t; //1 
     Integer i = new Integer(1); //2 
     t = new Test(); //3 
     System.out.println(Test4.a); //4 
    } 
} 

class Test { 
    private int a = 10; 
    private Test2 t2; //5 

    List<Test2> list = new ArrayList<Test2>() { 
     { 
      for (int i = 0; i < a; i++) { 
       add(new Test2()); //6 
      } 
     } 
    }; 
} 

class Test2 extends Test3{ 
} 

class Test3 { 
} 

class Test4 { 
    public static final int a = 4; 
} 

Io non so come (totalmente o parzialmente) e quando le classi vengono caricate. Quindi:

  1. Test t; - non è un uso attivo, ma il riferimento t deve essere un tipo definito di. È stata caricata la classe di test (forse parzialmente, quindi quante fasi - caricamento \ collegamento \ inizializzazione - è passata) o non è successo niente?
  2. Integer i = new Integer(1); - È stato caricato un numero intero all'avvio di JVM o su questa linea?
  3. t = new Test(); - un utilizzo attivo. È stato caricato completamente dall'inizio o da qualche punto (vedi 1)
  4. System.out.println(Test4.a); - è stato caricato Test4 o no?
  5. Sono stati caricati o meno Test2 e Test3? Se sì allora quando?

risposta

5

Quando le classi caricate sono coperte da JLS, Section 12.4.1.

Una classe o interfaccia tipo T vengono inizializzate immediatamente prima del primo verificarsi di uno qualsiasi dei seguenti:

  • T è una classe e viene creata un'istanza di T.

  • T è una classe e viene invocato un metodo statico dichiarato da T.

  • Viene assegnato un campo statico dichiarato da T.

  • Viene utilizzato un campo statico dichiarato da T e il campo non è una variabile costante (§4.12.4).

  • T è una classe di livello superiore (§7.6) e viene eseguita un'istruzione di asserzione (§14.10) annidata lessicale in T (§8.1.3).

(snip)

una classe o interfaccia non verranno inizializzate in qualsiasi altra circostanza.

Chapter 5 parla del caricamento, del collegamento e delle classi di inizializzazione.

Java Virtual Machine carica, collega e inizializza dinamicamente classi e interfacce. Il caricamento è il processo per trovare la rappresentazione binaria di un tipo di classe o interfaccia con un nome particolare e creare una classe o un'interfaccia da quella rappresentazione binaria. Il collegamento è il processo di prendere una classe o un'interfaccia e combinarla nello stato di runtime della Java Virtual Machine in modo che possa essere eseguita. L'inizializzazione di una classe o di un'interfaccia consiste nell'eseguire il metodo di inizializzazione della classe o dell'interfaccia (§2.9).

vostre questioni:

  1. dichiarazione di una variabile non carica la classe. Ma il caricamento avviene prima del collegamento e il collegamento avviene prima dell'inizializzazione. Quindi, quando una classe viene caricata, viene anche collegata e inizializzata.
  2. La classe Integer viene caricata dalla JVM (insieme a molte altre classi di basi linguistiche) prima dell'esecuzione del codice.
  3. Ora la classe Test viene caricata, poiché viene creata una nuova istanza.
  4. Test4 non è stato caricato, poiché è stata utilizzata solo una variabile costante, che è in conflitto con la quarta regola precedente.
  5. Test3 e Test2 sono stati caricati, dopo Test stato caricato, perché Test2 oggetti sono stati creati in Test s' esempio inizializzatore, che ha anche causato Test3 (superclasse) da caricare.

Questo è confermato quando running your code with the JVM option -verbose:class.

+0

Notando che l'inizializzazione non è la stessa del caricamento (o del collegamento). –

+0

Se la classe ** Test ** non è caricata sulla riga (1), allora quale tipo avrà variabile ** t **? –

+0

Nella JVM, la variabile 't' non esiste ancora; non è ancora stato assegnato. – rgettman