2009-03-25 9 views
5

Una volta caricata una classe esiste un modo per richiamare nuovamente gli inizializzatori statici?Richiamare nuovamente l'inizializzatore statico

public class Foo { 

    static { 
     System.out.println("bar"); 
    } 

} 

Edit:

Ho bisogno di invocare l'inizializzatore statico perché non ho scritto la classe originale e la logica che ho bisogno di invocare è implementato nel inizializzatore statico.

risposta

4

Una circostanza in cui la logica viene eseguita più di una volta è se la classe viene caricata più volte da diversi ClassLoaders. Nota che in questo caso, sono essenzialmente classi diverse.

Generalmente, tuttavia, si tratta di contratti one-shot. Se si desidera essere in grado di invocare la logica più volte, fare come altri hanno suggerito e inserirla in un metodo statico.

+0

Stavo cercando di trovare un riferimento sui classloader ma non sono riuscito a trovarne uno valido. Ne hai uno? –

+0

Ahimè, no. Le mie conoscenze sono messe insieme dalle specifiche VM, javadoc, manuali del server e varie fonti internet. Potresti fare peggio di Google "developerWorks" e "ClassLoader". – McDowell

10

Inserire il codice di inizializzazione in un metodo statico pubblico separato, quindi è possibile chiamarlo dall'inizializzatore statico e da altrove?

+0

Non riesco a modificare il codice. È in una libreria di terze parti e non intendo creare la mia distribuzione con il codice in un metodo statico regolare. :) La soluzione che ho usato è stata quella di copiare e incollare il codice in un'altra classe in modo che possa essere in un metodo statico regolare. Ma non mi è piaciuto.DRY – Kalecser

+0

Hm ... quindi la mia prossima domanda è: perché questa classe di terze parti ha una logica in un inizializzatore statico che si potrebbe voler reinvoke ?! –

+0

Carica ed elabora un file di configurazione XML sull'inizializzatore statico, voglio ricaricare l'xml. – Kalecser

4

Sono d'accordo con la risposta di Earwicker. Basta estrarre l'inizializzazione statica in un metodo statico separato.

public class Foo { 

    static { 
     Foo.initialize(); 
    } 

    public static void initialize() { 
     System.out.println("bar"); 
    } 

} 
+0

Perché il downvote? Può la persona che mi ha downvoted può spiegare perché? –

0

Si potrebbe provare ad estendere la classe che contiene il codice statico e quindi inserire il proprio inizializzatore statico. Non sono sicuro se funziona, ma:

public class OldBadLibraryClass { 
    static { 
     System.out.println("oldBadLibrary static init"); 
    } 
} 

//next file 

public class MyBetterClass extends OldBadLibraryClass { 
    static { 
     System.out.println("MyBetterClass init"); 
    } 
} 


public class Test { 
    public static void main(String[] args) { 
     new MyBetterClass(); 
    } 
} 

vedere se le stampe di cui sopra nell'ordine previsto. Sulla mia macchina, ha funzionato.

Anche se questo è totalmente un hack, ed è piuttosto fragile. Sarebbe molto meglio modificare la vecchia classe per avere un metodo init() che può essere sovrascritto.

0

Nel caso in cui si desideri veramente la risposta esatta alla propria domanda esatta, la risposta è no. Non è possibile richiamare un inizializzatore statico o un instanceInitializer tramite reflection.

La documentazione dice chiaramente:

per getDeclaredMethod(String name):

Se il nome è "<init>" o "<clinit>" un NoSuchMethodException è sollevata.

per getDeclaredMethods():

Il metodo di inizializzazione classe non è incluso nella matrice restituita.

Quindi no, non è possibile richiamarlo, anche tramite riflessione.