2016-04-26 60 views
0

據我所知,每當一個類被加載時,JVM就會爲它創建一個Class.class的對象,該JVM存儲所有加載類的元信息。如何編寫classname.class能夠返回對java.lang.Class對象的引用?

當我們使用forName(「classname」)方法時,它首先加載「classname」,然後爲它創建Class.class對象並返回對創建的Class.class對象的引用。

Example.java被給定爲:

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

Use.java是:

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()); 
       } 
     } 
} 

運行Use.java輸出:

Example Loaded 
Example 

的getClass()是一個方法,該方法只能用於物體。所以在創建對象之前,一定會加載一個類,併爲其創建Class.class的對象。

據「類和數據」的http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html節,「每當我們編譯任何Java文件,編譯器將嵌入在發出一個公共的,靜態的,最終的命名類別字段類型java.lang.Class的,字節碼「。我們可以使用這個字段:以上代碼的

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()); 
       } 
     } 
} 

輸出是:

Hello Example 

例的靜態身體得不到執行。意味着類的例子沒有被加載。

我的疑問是:

如果類沒有得到加載,然後也沒有得到它創造Class.class的對象。然後從聲明「Class c = Example.class」的語句中返回對Class.class的引用?

+0

查看鏈接問題,您的類當您訪問其靜態字段時,示例未初始化 – AdamSkywalker

回答

1

class loading and class initialization。 可以加載一個類,但不能初始化。情況-2發生這種情況。

類的靜態初始值設定項在類被初始化時運行,而不是在類被加載時運行。

Class.forName(String className)同時加載並初始化該類。因此,在情況1下,將打印Example Loaded

在-2的情況下,由於您沒有在做任何事情都會觸發類初始化Example Loaded將不會被打印。

也嘗試Class c = Class.forName("Example", false, Sample.class.getClassLoader());forName(它只加載類,但沒有初始化它),看看會發生什麼。

只要嘗試訪問類2(相同的代碼)中的靜態字段,看看會發生什麼。你

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); 

} 

也可以檢查哪些類被加​​載但使用java -verbose:class選項未初始化

+0

這意味着即使未初始化,也可以創建類Example的Class.class對象。字段「class」將與其他示例類信息一起加載到Method區域中。從方法區域JVM正在挑選對Class.class對象的「類」引用。我對麼? –

+1

@mynameisGYAN - 是的。隨着類的加載,類對象在JVM中創建。 – TheLostMind

+0

@mynameisGYAN - 使用'javap -v Example.class'並檢查*常量池下的#1#:) – TheLostMind

1

TheLostMind表示「類加載和類初始化之間存在差異。類初始化時運行靜態初始化程序,而當類被加載時運行,而不是當加載類」。

靜態成員被加載到方法區域中,因此名爲「」的字段被加載。

但是一個類沒有被初始化以訪問「static final」變量。

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導致

5 

但如果Example.i是

static int i = 5; 

然後運行Use.class結果:

Example Loaded 
5 

類似的事情發生的現場 「類」。正如TheLostMind告訴「類對象是在JVM中創建的,因爲類已加載」。字段「」在編譯時由編譯器初始化爲指向對象類。所以訪問Example.class我們可以訪問類對象。但是,訪問「類」字段不會使類初始化,因爲該字段是靜態的並且是最終的。

相關問題