如何编写classname.class能够返回对java.lang.Class对象的引用?

时间:2016-04-26 08:51:57

标签: java class reflection

据我所知,每当加载一个类时,JVM就会为它创建一个Class.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的对象。

根据" Class and Data" http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html的部分," 每当我们编译任何Java文件时,编译器都会在发出的字节代码中嵌入一个名为class的公共静态最终字段,类型为java.lang.Class。 &#34 ;.我们可以将此字段用作:

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的引用?

2 个答案:

答案 0 :(得分:1)

类加载类初始化之间存在差异。 可以加载类但不初始化。这种情况发生在-2。

类的静态初始化程序在类初始化时运行,而不是在类加载时运行。

Class.forName(String className)既加载又初始化类。因此,在案例1中,将打印Example Loaded

在-2的情况下,由于你没有任何东西来触发类初始化,因此不会打印Example Loaded

同时尝试Class c = Class.forName("Example", false, Sample.class.getClassLoader()); forNameclass 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); } (只加载类但不初始化它),看看会发生什么。

尝试访问第2类中的静态字段(相同代码),看看会发生什么。

java -verbose:class

您还可以使用List<x>选项检查哪些类已加载但尚未初始化

答案 1 :(得分:1)

正如TheLostMind所说“类加载和类初始化之间存在差异。类的静态初始化程序在类初始化时运行,而不是在类加载时运行”。

静态成员在方法区域加载,因此名为“ class ”的字段。

但是,为了访问“ 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

字段“ class ”也会发生类似的事情。正如TheLostMind所说,“类对象是在加载类时在JVM中创建的”。字段“ class ”由编译器初始化,在编译时指向对象类。因此,访问Example.class我们可以访问类对象。但是访问字段“class”并不会使类初始化,因为这个字段是静态的和最终的。