我们可以通过Class.forName和XX.class两种方式获得对象的 运行时类型信息(rtti),但这2种方式到底有什么区别呢?Class.forName("XX")的方式必将引起XX类的初始化,而XX.class并不引起XX的初始化,并且访问XX的static final类型的编译期常量也不会引起初始化.示例代码如下,请详细关注注释!
package com.test.rtti;
/** * 此程序演示如何获得类的Class对象 * 并演示类的初始化过程 */
import java.util.Random;
class Initable
{
//static final类型的编译期常量,可以在此类初始化前被调用
static final int staticFinal1 = 47;
//static final类型的运行期常量,调用此变量则引起类的初始化.
static final int staticFinal2 = ClassInit.rand.nextInt(1000);
//静态代码块,如果初始化,则此块代码将执行
static
{
System.out.println("Initializing Initable");
}
}
class Initable2
{
//static 但不是final类型的编译期常量,调用它将引起类的初始化.
static int staticNonFinal = 147;
static
{
System.out.println("Initializing Initable2");
}
}
class Initable3
{
static int staticNotFinal = 74;
static
{
System.out.println("Initializing Initable3");
}
}
public class ClassInit
{
public static Random rand = new Random(47);
public static void main(String[] args)
{
//通过.class拿到Class对象,不会引起类的初始化
//但通过Class.forName("com.davy.rtti.Initable")拿到Class对象一定回获得初始化
@SuppressWarnings("unused")
Class initable = Initable.class;
System.out.println("After creating Initable ref");
System.out.println(Initable.staticFinal1);//不会引起初始化
System.out.println(Initable.staticFinal2);//会引起初始化
try
{
@SuppressWarnings("unused")
Class initable3 = Class.forName("com.davy.rtti.Initable3");//会引起初始化,注意写全包名.
System.out.println("after creating Initable3 ref");
System.out.println(Initable3.staticNotFinal);
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}