2016-08-03 17 views
1

Im folgenden Java-Code wird die Insect-Klasse von der Beetle-Klasse geerbt.Java - Was ist die Reihenfolge der Initialisierung in diesem Code?

class Insect { 

    private int i = 9; 
    protected int j; 

    Insect() { 
     System.out.println("i = " + i + ", j = " + j); 
     j = 39; 
    } 
    private static int x1 
      = printInit("static Insect.x1 initialized"); 

    static int printInit(String s) { 

     System.out.println(s); 
     return 47; 
    } 
} 

public class Beetle extends Insect { 

    private int k = printInit("Beetle.k initialized"); 

    public Beetle() { 
     System.out.println("k = " + k); 
     System.out.println("j = " + j); 
    } 
    private static int x2 
      = printInit("static Beetle.x2 initialized"); 

    public static void main(String[] args) { 
     System.out.println("Beetle constructor"); 
     Beetle b = new Beetle(); 
    } 
} 

Der Ausgang ist irgendwie kompliziert.

statischen Insect.x1 initialisiert

statischen Beetle.x2

initialisiert

Beetle Konstruktor

i = 9, j = 0

Beetle.k

initialisiert

k = 47 j = 39

Wie lautet die Reihenfolge der Initialisierung in diesem speziellen Beispiel?

Warum wird x2 sofort nach x1 initialisiert? Und warum ist die erste Zeile der Hauptmethode (System.out.println("Beetle constructor");), nach x1 und x2 Initialisierung ausgeführt. So verwirrend.

Ich weiß, dass der abgeleitete Klassenkonstruktor den Basisklassenkonstruktor automatisch aufruft (es sei denn, es hat Parameter und Sie würden das Schlüsselwort super verwenden). Ich weiß, dass Variablen vor dem Konstruktor initialisiert werden und dass statische Variablen vor anderen Variablen initialisiert werden.

Antwort

4

x1 und x2 sind statisch. Dies bedeutet, dass sie initialisiert werden, wenn die Klasse geladen wird. Da die Hauptmethode in Beetle ist, muss die Klasse vor dem Aufruf main geladen werden. Deshalb ist x1 und x2 Initialisierung das erste, was Sie sehen. Nicht sicher, warum die Reihenfolge der beiden so ist wie sie ist.

Jetzt rufen Sie main und System.out.println("Beetle constructor"); wird ausgeführt. Dann ruft es Beetle() an, die zuerst super() (alias Insect()) implizit aufruft. Dies druckt i = 9, j = 0 weil i 9 und j hat zu diesem Zeitpunkt nicht initialisiert wurde, was bedeutet, dass es den Standard int Wert 0.

Jetzt j wird auf 39 und die Strömung weiter in Beetle(). Dies initialisiert jetzt die Felder Beetle, in Ihrem Fall k. Wenn es also um den expliziten Code in Beetle() geht, wird k vom Superkonstrukteur auf 47 und j bis 39 initialisiert.

+0

Ich könnte also sagen, als allgemeine Regel, dass: 1. Statische Elemente in der Basisklasse zuerst initialisiert werden, 2. Statische Mitglieder in der abgeleiteten Klasse als nächstes, 3. Basisklasse nicht statisch initialisiert Elemente (Primitive und Referenzen) werden initialisiert. 4. Basisklassenkonstruktor wird aufgerufen. 5. Nicht statische Member der abgeleiteten Klasse werden initialisiert. 6. Schließlich habe ich alles, was ich brauche, um das Objekt zu erstellen, also wird der abgeleitete Klassenkonstruktor aufgerufen. Bin ich richtig? –

+1

@HelloLili in diesem einfachen Fall ja, aber ich wäre vorsichtig mit der Verwendung als allgemeine Regel. Java arbeitet nach einer Reihe von Regeln, die in der Java-Sprachspezifikation definiert sind. Ich denke, Sie sollten besser lernen, wie bestimmte Aktionen ausgelöst werden. Anstelle von "statischen Mitgliedern zuerst" erinnere dich daran, dass "das Laden einer Klasse die Initialisierung der statischen Mitglieder auslöst" und so weiter. –

2

Dies erklärt sich wie folgt zusammen -

Da statische Mitglieder sind nicht-Instanz Mitglieder nur eine Kopie des Elements d.h wird über alle Instanzen der Klasse geteilt werden diese Elemente zunächst initialisiert.

In diesem Fall wird x1 zuerst initialisiert, da es ein statisches Element ist, das in der Basisklasse der Klasse vorhanden ist, in der die Hauptmethode vorhanden ist.

Daher wird 1st x1 initialisiert.

Das statische Element x2 in der Unterklasse folgt aus dem gleichen Grund und auch, weil keine anderen statischen Elemente in vorhanden sind. Insektenklasse.

Beetle Konstruktor Zeile wird von der Hauptmethode gedruckt.

Die Konstrukteure der Superklasse und Unterklasse sind eine nach der anderen aus offensichtlichen Gründen genannt

2

JVM (Class Loader) lädt Beetle Klasse, wenn Sie seine Haupt statische Methode aufrufen. Nach dem Laden der Klasse findet die Initialisierung der Beetle-Klasse statt, was bedeutet, dass alle statischen Mitglieder der Klasse initialisiert werden.

Die Basisklasse wird immer implizit initialisiert. Daher wird x1 vor x2 initialisiert.

Sie sehen den "Beetle-Konstruktor" nach x1 und x2, denn wenn Sie auf eine statische Methode einer Klasse verweisen (wie Sie main aufrufen), springt die JVM-Ausführungsreihenfolge zur Initialisierung der statischen Klassenelemente , bevor Sie mit der Ausführung der Methode main() fortfahren.

Als Experiment versuchen, das Hauptverfahren zu einer anderen Klasse zu entfernen,

public class Beetle1 { 
public static void main(String[] args) { 
     System.out.println("Beetle1 constructor"); 
    } 
} 

Jetzt, da der Käfer-Konstruktor nicht referenziert wird, wird die Klassenlade es nicht geladen werden, und Sie werden Beetle1 Konstruktor gedruckt sehen.

Verwandte Themen