2016-04-26 9 views
0

Nach meiner Kenntnis wird jedesmal, wenn eine Klasse geladen wird, ein Objekt von Class.class dafür von JVM erstellt, das alle Metainformationen der geladenen Klasse speichert.Wie schreibt classname.class den Verweis auf das java.lang.Class-Objekt?

Wenn wir forName ("Klassenname") -Methode verwenden, lädt es zuerst "Klassenname" und erstellt dann das Class.class-Objekt und gibt den Verweis auf das erstellte Class.class-Objekt zurück.

Example.java ist gegeben als:

class Example 
{ 
     static 
     { 
       System.out.println("Example Loaded"); 
     } 
     Example() 
     { 
       System.out.println("Example Constructed"); 
     } 
} 

Use.java ist:

import java.lang.reflect.*; 
class Use 
{ 
     int i; 
     public static void main(String[] args) throws Exception 
     { 
       Class c = Class.forName("Example"); 
       Constructor[] con = c.getDeclaredConstructors(); 
       for(Constructor x: con) 
       { 
         System.out.println(x.getName()); 
       } 
     } 
} 

Lauf Use.java Ausgänge:

Example Loaded 
Example 

getClass() ist ein Verfahren, das kann nur mit Objekten verwendet werden. Also wird definitiv vor der Objekterstellung eine Klasse geladen und das Objekt der Class.class wird dafür erstellt.

Nach dem Abschnitt "Class and Data" von http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html, "Immer, wenn wir eine Java-Datei kompilieren, wird der Compiler ein öffentliches, statisches, letztes Feld mit dem Namen class des Typs java.lang.Class in das emited einbetten Bytecode ". Wir können dieses Feld verwenden, wie:

import java.lang.reflect.*; 
class Use 
{ 
     int i; 
     public static void main(String[] args) throws Exception 
     { 
       Class c = Example.class; 
       Constructor[] con = c.getDeclaredConstructors(); 
       for(Constructor x: con) 
       { 
         System.out.println("Hello "+x.getName()); 
       } 
     } 
} 

Ausgabe des obigen Codes ist:

Hello Example 

Statische Körper von Beispiel nicht ausgeführt werden sollen. Bedeutet, dass die Klasse Beispiel nicht geladen wurde.

Mein Zweifel ist:

Wenn Klasse dann nicht Gegenstand des Class.class geladen bekommt auch nicht dafür geschaffen bekommen. Dann von wo die Anweisung "Klasse c = Example.class" den Verweis auf Class.class zurückgibt?

+0

siehe die verknüpfte Frage, Ihre Klasse Beispiel wird nicht initialisiert, wenn Sie auf sein statisches Feld zugreifen – AdamSkywalker

Antwort

1

Es gibt einen Unterschied zwischen Klasse laden und Klasseninitialisierung. Eine Klasse kann geladen, aber nicht initialisiert werden. Dies geschieht in Fall -2.

statische Initialisierer einer Klasse werden ausgeführt, wenn die Klasse initialisiert wird und nicht wenn die Klasse geladen wird.

Class.forName (String Klassenname) lädt und initialisiert die Klasse. Daher wird in Fall 1 Example Loaded gedruckt.

In Fall -2, da Sie nichts tun, um die Klasseninitialisierung auszulösen, wird Example Loaded nicht gedruckt.

Versuchen Sie auch Class c = Class.forName("Example", false, Sample.class.getClassLoader()); Version von forName (die nur lädt die Klasse, aber initialisiert es nicht) und sehen, was passiert.

Versuchen Sie einfach auf ein statisches Feld in Klasse 2 (gleicher Code) zuzugreifen und sehen Sie, was passieren wird.

class Example 
{ 
    static int i= 5; 
     static 
     { 
       System.out.println("Example Loaded"); 
     } 
     Example() 
     { 
       System.out.println("Example Constructed"); 
     } 
} 

public static void main(String[] args) { 
    Class c = Example.class; 
    Constructor[] con = c.getDeclaredConstructors(); 
    for(Constructor x: con) 
    { 
      System.out.println("Hello "+x.getName()); 

    } 
    System.out.println(Example.i); 

} 

Sie können auch überprüfen, welche Klassen werden geladen, aber nicht mit java -verbose:class Option initialisiert.

+0

Das bedeutet Class.class -Objekt für Klasse Beispiel kann erstellt werden, auch wenn es nicht initialisiert ist. Das Feld "class" wird im Method-Bereich mit anderen Beispiel-Klasseninformationen geladen. Aus dem Methodenbereich wählt JVM den Verweis "class" auf das Objekt Class.class für das Beispiel. Hab ich recht? –

+1

@mynameisGYAN - Ja. Klassenobjekte werden in der JVM erstellt, wenn Klassen geladen werden. – TheLostMind

+0

@mynameisGYAN - Verwenden Sie 'javap -v Example.class' und markieren Sie' # 1 'unter * constant pool * :) – TheLostMind

1

Da TheLostMind sagte "gibt es einen Unterschied zwischen Klassen laden und Klasseninitialisierung. Statische Initialisierer einer Klasse werden ausgeführt, wenn die Klasse initialisiert wird und nicht wenn die Klasse geladen wird".

Statische Elemente werden in Methodenbereich geladen und so das Feld "Klasse".

Eine Klasse wird jedoch nicht für den Zugriff auf eine "statische endgültige" Variable initialisiert.

Example.java

class Example 
{ 
     static final int i = 5; 
     static 
     { 
       System.out.println("Example Loaded"); 
     } 
     Example() 
     { 
       System.out.println("Example Constructed"); 
     } 
} 

Use.java

import java.lang.reflect.*; 
class Use 
{ 
     public static void main(String[] args) throws Exception 
     { 
       System.out.println(Example.i); 
     } 
} 

Use.class Laufergebnisse

5 

Aber wenn Example.i war

static int i = 5; 

dann Use.class Lauf Ergebnisse als:

Example Loaded 
5 

ähnliche Sache mit dem Feld "Klasse" geschieht. Wie TheLostMind sagte: "Klassenobjekte werden in der JVM erstellt, wenn Klassen geladen werden". Feld "Klasse" vom Compiler initialisiert, um beim Kompilieren auf Objektklasse zu zeigen. Durch Zugriff auf Example.class können wir auf das Klassenobjekt zugreifen. Durch den Zugriff auf das Feld "class" wird die Klasse jedoch nicht initialisiert, da dieses Feld statisch und final ist.

Verwandte Themen