2015-07-20 20 views
16

Wie pro JLS:Erstellen ein Objekt einer Klasse in einem eigenen statischen Initialisierer

A-Klasse oder Schnittstelle Typ T wird unmittelbar vor dem ersten Auftreten von einem der folgenden Schritten initialisiert wird:

T ist eine Klasse und eine Instanz von T wird erstellt.

Auch sagt er,

Initialisierung einer Klasse besteht seine statische initializers der Ausführung und die Initialisierungen für statische Felder (Klassenvariablen) in der Klasse deklariert

Daraus schließe ich zwei Punkte

  • Klasseninitialisierung besteht
  • Klasseninitialisierung geschieht seine statischen Initialisierungen auszuführen, wenn eine Klasse instanziiert wird.

Jetzt

Ich gehe davon aus, wenn ich ein Objekt einer Klasse-Test in seiner eigenen (Test eigenen) statische Initialisierer schaffen sollte es mir einen Stapelüberlauf werfen, da es sich immer wieder, weil gemäß der oben nennen sollte zwei Punkte, Instanziierung der Klasse sollte die Klasse initialisieren und Initialisierungsblock hat die Instanziierung der Klasse. Ein Stapelüberlauf tritt auf, wenn ich die Klasse in einem eigenen Konstruktor oder in einem eigenen Instanzinitialisierer instanziiere.

Zum Beispiel

public class Test { 

    static{ 
     System.out.println("static test"); 
     new Test(); 
    } 
    { 
     //new Test(); // This will give a stack overflow 
     System.out.println("intializer"); 
    } 

    public Test(){ 
     //new Test(); // This will give a stack overflow 
     System.out.println("constructor"); 
    } 
    public static void main(String[] args) { 
    } 

} 

jedoch das Ergebnis etwas anders ist.

Ergebnis:

statischer Test intializer Konstruktor

Entweder ich bin zu verwirrt, um die Initialisierung der Klasse zu verstehen, oder ich entschuldige mich, wenn ich etwas sehr offensichtlich bin hier fehlt und schätze deine Hilfe.

+2

statische Block wird nur einmal aufgerufen .. Warum denkst du, es wird oft aufgerufen werden? – Constantin

+0

@Constantin Weil die JLS so sagt. (Oder genauer, es bedeutet, dass in diesem Fall der statische Initialisierer laufen muss, bevor der statische Initialisierer läuft) – immibis

+0

Constantin, danke für die Antwort, ich dachte, dass der statische Block wiederum das Objekt der Klasse selbst erzeugt, das die Klasse initialisieren würde wieder (duh auf mich, wenn das blooper ist, aber ich bin hier verwirrt), trotzdem glaube ich, statische Block wird nur einmal aufgerufen und dieser Block ist Instanziierung der Klasse selbst, die nichts anderes als ein Singleton-Objekt ist? – chebus

Antwort

15

Schritt 3 der Klasse Initialisierungsprozedur, in JLS section 12.4.2 angegeben,

ist, wenn das Klassenobjekt für C, daß die Initialisierung für C durch den aktuellen Thread im Gang anzeigt, muss diese eine rekursive Anforderung sein, Initialisierung. Release LC und normal fertig.

Beim Erstellen einer Instanz einer Klasse in ihrem statischen Initialisierer wird die Klasse nicht rekursiv neu initialisiert; rekursive Initialisierungsanforderungen werden erkannt und tun nichts.

(Beachten Sie, dass "normal abschließen" bedeutet "die Operation ist getan", nicht "folgen Sie den Schritten, die normalerweise befolgt werden, um den Vorgang abzuschließen"; es ist im Gegensatz zu "abrupt abzuschließen", was bedeutet, dass wir eine Art haben von Ausnahme oder Fehler.)

+0

Gut finden Sie Dank für die Antwort. – chebus

+0

Release LC und schließt normal .. wie? Ich meine, da es rekursiver Aufruf ist, versucht der aktuelle Thread die Klasse zu initialisieren, bei der der statische Klassencode die Initialisierung anfordert, wie er glatt enden wird. Können Sie, wenn möglich, etwas mehr erklären? – Babel

+0

@Babel: "Complete normal" ist ein Fachbegriff, der an anderer Stelle definiert ist. Es bedeutet im Grunde, dass wir fertig sind; Es bedeutet nicht, dass wir etwas anderes tun müssen, um zu beenden. – user2357112

2

Der statische Initialisierer wird nur aufgerufen, wenn die Klasse geladen wird. Das Instanziieren eines Objekts im statischen Initialisierer führt nicht dazu, dass die Klasse erneut geladen wird, das Klassenladen einer Klasse erfolgt nur einmal, der Klassenlader speichert die Klasse für die Lebensdauer der JVM-Instanz zwischen.

Wenn Sie eine neue Instanz im Instanzinitialisierer oder im Konstruktor erstellt haben, erhalten Sie den Stackoverflow-Fehler.

+0

danke für die Antwort, Hauptausführung Thread lädt die Testklasse nur über Classloader nur einmal und das Objekt in der statischen Initialisierung ist Singleton – chebus

Verwandte Themen