上一篇博客中我们提到了ClassLoader,知道ClassLoader是用来动态加载某个Class文件到内存当中,但是这个Class文件是怎么生成的呢?从何而来?这又涉及到另一个概念—java.lang.Class。
Class 是java的一个特殊类,对于我们定义的类、接口,它更算是一个抽象类。Class类用于封装被装入到JVM中的类(包括类和接口)的信息。 当一个类和接口被装入JVM时,就自动创建一个Class类的实例来表示这个类,也就是我们说的Class对象,收集了当前这个对象的基本信息,包括属性、方法、构造器、接口、父类等。
注意:Class类没有公共构造方法,Class对象是在加载类时由JVM以及类加载器中的defineClass()自动构造的。 所以Class类是类加载器的信息来源者。
一、获取Class对象方式
1. 利用类名.Class方式直接获得与指定关联的Class对象,而并不需要有该类的对象存在。
示例:
public class ReflactionTest {
@Test
public void testClass() throws ClassNotFoundException {
Class clazz = null;
//1.直接通过类名.class的方式得到
clazz = Person.class;
System.out.println(clazz);
}
2. 利用Object.getClass()方法获取该方法对象所属关联的Class对象。
示例:
public class ReflactionTest {
@Test
public void testClass() throws ClassNotFoundException {
String str1 = new String();
String str2 = new String();
Class cl1= str1.getClass();
Class cl2 = str2.getClass();
System.out.println(cl1.getName());//得到类的完整名称
System.out.println(cl1==cl2);
}
控制台输出: java.lang.String
true
上面代码中,getClass方法用于返回封装String类型的Class对象,getName返回封装的类的名称。同时cl1和cl2返回相同的对象,所以cl1==cl2返回true。
注意:对于相同的类,JVM只会载入一次,与该类对应的Class对象也只会存在一个,无论你实例化了几个。
3. 利用Class.forName()静态方法,该方法根据指定的类名获取与该类关联的对象。如果该类还没有被装入,该方法会将该类装入JVM。
示例:
public class Person {
public Person() {
System.out.println("Person()");
}
static {
System.out.println("Person is initialized");
}
}
运行下面的代码:
public class ReflactionTest {
@Test
public void testNewInstance() throws ClassNotFoundException {
String className = "com.tgb.reflectiontest.Person";
Class clazz = Class.forName(className);
}
控制台输出:Person is initialized
Class.forName()方法,首先会将字符串指定的类装入JVM,并返回与之关联的Class对象,JVM装入后对其进行初始化,调用static块中的代码。 forName方法的参数必须要是类的完整指定名。
二、其他常用方法:
- getClassLoader(): 该方法用于返回该Class对象代表的类的类加载器。如果类的加载器为Bootstrap,则返回NUll.
- getSuperClass(): 该方法返回的是这个Class对象所代表的的JAVA类的父类对应的Classs对象。
- isArray() :判定此Class对象是否表示一个数组类。
- getInterfaces(): 确定此对象所表示的类或接口实现的接口。
- newInstance()方法使用所选的Class对象生成该类的新实例。它调用无参数的类构造器生成新的对象。对于newInstance()来说,可以在没有任何对象存在的情况下,使用它创建一个新的对象。
示例:
<pre name="code" class="java">public class ReflactionTest {
@Test
public void testNewInstance() throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
String className = "com.tgb.reflectiontest.Person";
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();
System.out.println(obj);
}
}
上面代码,首先使用Class.forName得到Class对象,即该方法要求JVM查找并加载指定的Person类,并执行Person的静态代码段,动态加载和创建出Person对象。只有当执行了newInstance()方法时,才会实例化出一个对象来。
注意: 使用newInstance()创建的类必须有一个默认构造器。
总结:Class类总的来说也是一个类,这个类收集当前对象的基本信息(属性、方法、构造器、父类、接口)。Class对象只能由系统创建,每个类只能有一个实例。 对于每个类而言,都有一个Class类型的对象来保存这个类的信息。
Class 和ClassLoader都是反射技术的基础,需要我们掌握其原理。