Questo è il compito del caricatore classe.Il caricamento della classe in java inizia con il bootloader bootstrap. Questo caricatore di classi carica prima tutte le classi nella libreria java standard, lo rt.jar.
Quindi viene richiamato il programma di caricamento classe . Carica tutte le classi dai file jar di estensione installati in una directory ext JVM. Ora finalmente viene richiamato il classloader del classpath.
Il classloader del percorso classe inizia a caricare le classi dalla classe principale, la classe che ha il metodo principale definito. Una volta caricato, esegue qualsiasi inizializzatore statico in quella classe. Durante l'esecuzione dell'inizializzatore, se incontra una classe che non è caricata, interrompe l'esecuzione del blocco statico, carica prima la classe e infine riprende l'esecuzione di quel blocco statico.
Pertanto, non è possibile che si verifichino chiamate a classi non caricate. Vediamo questo con il vostro esempio, il cui codice è simile a questo:
class A
{
public final static List<Integer> list;
static
{
System.out.println("Loaded Class A");
list = new ArrayList<>();
}
}
class B
{
public final static int dependsOnA;
static
{
System.out.println("Loaded Class B");
dependsOnA = A.list.size();
}
}
Qui, in questo esempio, non v'è in realtà alcun metodo principale, in modo queste classi non verranno effettivamente caricati nella memoria. Supponiamo, aggiungiamo la seguente classe principale al codice precedente.
class C
{
static
{
System.out.println("Loaded Class C");
}
public static void main(String[] args)
{
System.out.println(B.dependsOnA);
}
}
Vediamo cosa questo produrrebbe nell'output: http://ideone.com/pLg3Uh
Loaded Class C
Loaded Class B
Loaded Class A
0
Cioè, prima della classe C è caricato, perché aveva il metodo principale. Una volta caricato, viene richiamato l'inizializzatore statico della classe C. Si noti, tuttavia, che il metodo principale viene richiamato dopo il caricamento del blocco statico della classe C.
Ora il metodo principale, abbiamo stampato il valore di dependsOnA
di classe B. Ora, il caricatore di classe interrompe l'esecuzione questa affermazione, e carica la classe B, e lo esegue è blocco statico, che a sua volta, assegna la variabile dependsOnA
con il valore del numero di elementi nell'elenco di classe A, che non è caricato.
Quindi il caricatore di classi salta da lì, carica la classe ora e richiama il blocco statico della classe A e viene creato un elenco. Ora dal momento che non ci sono più classi da caricare, il programma di caricamento classi ritorna al blocco statico di classe B e l'assegnazione è completa. Ora finalmente, il controllo è ora con il metodo principale e il valore di dependsOnA
viene stampato sulla console.
Spero che questo aiuti.
Da un punto di vista * design *, suggerisco caldamente che non è una buona idea per la classe 'A' rendere * public * la sua proprietà' list', in primo luogo. Invece, l'avrei reso privato e fornito * metodi * in 'A' che forniscono a tutte le altre classi" le cose che devono sapere e la capacità di fare le cose che devono fare ". Un vantaggio molto importante è che, ora, la classe 'A' è sia autonoma che auto-descrittiva. Tutto il codice necessario per garantire che la classe 'A' funzioni correttamente, è * in * class' A', il cui codice è protetto da interferenze o effetti collaterali (come 'B'). –
... anche: "Cosa può fare' A' e cosa possono fare gli altri per 'A'?" A questa domanda può ora essere data una risposta, in via definitiva, guardando * solo * a 'A'. La differenza di runtime tra i due è trascurabile, ma il design, IMHO, è molto più robusto e debugabile. (E, molto meno dipendente da "esattamente quando Java fa questo o quello".) Sottoscrivo che è un buon principio dire: "non lasciare che le altre classi si intromettano negli affari di altre classi". Per quanto sia saggio per gli umani ("che sono croccanti e gustosi con i fagioli Fava ...") non per intromettersi con i draghi. –
se la lista è già statica wouldnt A.list.size() l'accesso diretto è più efficiente? –