Class是反射的基础,我们先看看API的说明:
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。 Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
注意几个关键语句:
1、共享该 Class 对象,证明Class是一个对象
2、Class 没有公共构造方法,证明创建Class对象时不会调用构造方法来创建Class对象(我们知道普通对象的创建都会去调用构造方法来实现创建)
3、Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。这里类加载器证明是在我们需要的时候把.class动态加载到内存,并创建对象,创建对象的类型为Class
2、我们再来看看几段代码:
普通类Cat
public class Cat {
// 静态模块
static {
System.out.println("我是静态内容");
}
// 无参构造方法
public Cat() {
System.out.println("我是构造方法");
}
}
测试类1
public class T {
@Test
public void testClass() throws InstantiationException, IllegalAccessException, ClassNotFoundException{
Class<?> cl= Class.forName("com.lovo.Cat",true,Cat.class.getClassLoader());
System.out.println(cl.toString());
}
}
运行结果:
我是静态内容
class com.lovo.Cat
class com.lovo.Cat
测试类2
public class T {
@Test
public void testClass() throws InstantiationException, IllegalAccessException, ClassNotFoundException{
Class<?> cl= Class.forName("com.lovo.Cat",true,Cat.class.getClassLoader());
//System.out.println(cl.toString());
System.out.println(cl.newInstance());
//Cat cat=new Cat();
}
}
运行结果:
我是静态内容
我是构造方法
com.lovo.Cat@18bf6bf
我是构造方法
com.lovo.Cat@18bf6bf
分析结果:
1、测试类1静态模块代码打印在控制台上,证明Cat类已经加载到内存,因为我们知道静态代码在类加载的时候会去实例化放(静态类我们都是去点出方法或属性而不是先去new对象,因为在类加载时候已经实例化放入到静态池),这里仅代表加载到内存
2、我们注意到Cat的构造方法并没执行,说明Cat并没有被实例化,而我们在测试1用了一个Class来接收(想一想我们普通类被new时都会用一个类型进行接收),所以这时候只代表我们创建了Class对象,在这个对象中我们可以得到此对象引用类的所有方法、属性、构造方法、修饰,这就为反射做好铺垫。
3、测试2调用Class对象的newInstance()方法,结果静态模块执行,构造方法也执行,证明我们在调用newInstance()方法时,虚拟机把Class对象再次实例化成一个具体的Object对象,此时就和我们new Cat() 是一回事调用构造方法来实例化对象。