2016-09-09 2 views
2

Was bedeutet es, wenn wir sagen, ein class ist "geladen"?Wann sagen wir, dass die Klasse in Java geladen ist?

Zum Beispiel wird gesagt, dass Static init Blöcke zum Zeitpunkt des Ladens der Klasse ausgeführt werden. Wann genau ist class geladen?

Bitte beachten Sie diesen Code von Kathy Sierra Buch:

class Bird { 
    { 
     System.out.print("b1 "); 
    } 
    public Bird() { 
     System.out.print("b2 "); 
    } 
} 

class Raptor extends Bird { 
    static { 
     System.out.print("r1 "); 
    } 
    public Raptor() { 
     System.out.print("r2 "); 
    } 
    { 
     System.out.print("r3 "); 
    } 
    static { 
     System.out.print("r4 "); 
    } 
} 

class Hawk extends Raptor { 
    public static void main(String[] args) { 
     System.out.print("pre "); //1 
     new Hawk();//2 
     System.out.println("hawk "); 
    } 
} 

Der Ausgang des obigen Code ist: r1 r4 pre b1 b2 r3 r2 Habicht

Ich kann nicht howcome pre verstehen gedruckt wird nach r1. Welcher Teil des Codes wurde in die Raptor-Klasse geladen?

Einer der Antwort sagt:

„die Klasse im allerletzten Moment initialisiert wird, aber bevor eines seiner Mitglieder zugegriffen wird“.

Aber durch diese Logik, sollte nicht VOR r1 gedruckt werden? Seit Zeile 2 greift Konstruktor der Klasse Raptor NACH der Ausführung von line1.

+0

Kommt das nicht auf Ihre Definition von "geladen"? – byxor

+0

Eine Klasse wird geladen, wenn Sie einen Verweis auf diese Klasse haben können. Die Initialisierung ist ein späterer Schritt, der oft zusammen durchgeführt wird, aber nicht unbedingt sein muss. –

+0

@PeterLawrey Tritt dies vor dem Beginn der Ausführung der Methode main() auf? – SKG

Antwort

4

Verwechseln Sie nicht Klasse Laden, die Umsetzung spezifisch ist, und Klasse Initialisierung, die sehr streng festgelegt ist. Leider werden diese beiden Begriffe oft verwendet, als ob sie dasselbe bedeuten, aber normalerweise bezieht sich der Ausdruck "die Zeit des Klassenladens" auf die Zeit der Klasse Initialisierung.

Als eine Zusammenfassung der detaillierten Fall-zu-Fall-Regeln wird die Klasse zum letztmöglichen Zeitpunkt initialisiert, aber bevor auf eines ihrer Mitglieder zugegriffen wird.

Mit diesem Teil aufgeklärt, im Code Ihres Beispiels haben Sie eine Klasse Hawk extends Raptor extends Bird. Hawk ist die Klasse, die den Einstiegspunkt Ihres Programms enthält, die Methode main. Dies ist der Init-Auftrag:

  1. Starten Sie die Initialisierung Hawk. Ist die Elternklasse Raptor initialisiert? Nein.
  2. Starten Sie die Initialisierung Raptor. Ist das übergeordnete Element Bird initialisiert? Nein.
  3. Starten Sie die Initialisierung Bird.
  4. Vollständige Initialisierung Bird.
  5. Führen Sie die statischen Init-Blöcke Raptor aus. Dies druckt r1 r4.
  6. Vollständige Initialisierung Raptor.
  7. Vollständige Initialisierung Hawk.
  8. Starten Sie die Ausführung Hawk.main(). Dies druckt pre.
+0

Hallo Marko, ich habe die Frage bearbeitet. Kannst du es bitte nochmal anschauen? – SKG

+0

Ich habe die Antwort bearbeitet. –

+0

Vielen Dank für die Erklärung. Ich habe die Konstruktorverkettung komplett vermisst. Ich denke jedoch, dass Ihr 5. Punkt mit der Bearbeitung vollständiger wäre: Führen Sie Raptors "statische" Init-Blöcke aus. – SKG

0

Normalerweise, wenn Sie zuerst versuchen, die Klasse zu verwenden, z. Versuchen Sie, eine Instanz zu erstellen, eine ihrer statischen Methoden zu verwenden oder einen Verweis auf das Objekt 'Class<?>' der Klasse zu speichern.

Beachten Sie, dass dies von der Implementierung des Klassenladeprogramms abhängen kann.

0

Verschiedene JVMs laden Klassen auf verschiedene Arten, aber die Grundregel ist nur das Laden von Klassen, wenn sie benötigt werden. Wenn andere Klassen von der geladenen Klasse benötigt werden, werden sie ebenfalls geladen. Der Ladevorgang ist rekursiv.

Unten Code ist ein einfaches Beispiel für Klasse und statischen Block, Variable Laoding.

public class Foo { 

    //instance variable initializer 
    String s = "abc"; 

    //constructor 
    public Foo() { 
     System.out.println("constructor called"); 
    } 

    //static initializer 
    static { 
     System.out.println("static initializer called"); 
    } 

    //instance initializer 
    { 
     System.out.println("instance initializer called"); 
    } 

    public static void main(String[] args) { 
     new Foo(); 
     new Foo(); 
    } 
} 

Ausgang für obiges Programm:

static initializer called 
instance initializer called 
constructor called 
instance initializer called 
constructor called 
+0

Wenn Sie main() -Methode vollständig leer ist. Es druckt immer noch "statischer Initialisierer namens". Zu welchem ​​Zeitpunkt wird gerade die Foo-Klasse geladen? – SKG

+0

Die main() -Methode ist in der Foo-Klasse vorhanden. Wenn wir versuchen, das Programm auszuführen, wird es beginnen, Startpunkt zu finden, d. H. Main() -Methode in unserem Projekt. In diesem Szenario ist die main() -Methode in der Foo-Klasse vorhanden. Classloader lädt daher die Foo-Klasse in den Speicher, um die Hauptmethode auszuführen. Während also die Foo-Klasse in den Speicher geladen wird, werden auch andere Parameter wie statische Blöcke und Variablen geladen. – Abhijeet

Verwandte Themen