2016-04-26 47 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我们可以访问类对象。但是,访问“类”字段不会使类初始化,因为该字段是静态的并且是最终的。