据我所知,每当加载一个类时,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的引用?
答案 0 :(得分:1)
类加载和类初始化之间存在差异。 可以加载类但不初始化。这种情况发生在-2。
类的静态初始化程序在类初始化时运行,而不是在类加载时运行。
Class.forName(String className)既加载又初始化类。因此,在案例1中,将打印Example Loaded
。
在-2的情况下,由于你没有任何东西来触发类初始化,因此不会打印Example Loaded
。
同时尝试Class c = Class.forName("Example", false, Sample.class.getClassLoader());
forName
版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);
}
(只加载类但不初始化它),看看会发生什么。
尝试访问第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”并不会使类初始化,因为这个字段是静态的和最终的。