一、什么是反射?
反射是指计算机程序在运行时访问、检测和修改它本身状态或行为的一种能力,是一种元编程语言的特性,有许多语言都提供了对反射机制的支持,她使程序能够编写程序,Java的反射机制使得Java能够动态的获取类的信息和调用对象的方法。
二、反射机制的功能
- 在运行时可以知道任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时获取任意一个类所具有的成员变量和方法信息
- 在运行时可以调用任意一个对象的方法
- 生成动态代理
三、Java反射机制及基本用法
在Java中,Class是反射编程的起点,代表运行时类型信息(Run-Time Type Identification)。java.lang.reflect包中包含了Java支持反射的主要组件,如Constructor、Field、Method等,分别表示类的构造器、属性、方法,关系如下图:
Constructor和Method与Field的区别在于前者继承自抽象类Executable,是可以在运行时动态调用的,而Field仅仅具备可访问的特性,且默认为不可访问。下面了解下它们的基本用法:
四、Java反射API用法
- 获取Class三种方式
// 1. 采用Class.forName获取类的Class对象
Class clazz = Class.forName("com.zhq.test.ReflectTest");
System.out.println("clazz:" + clazz);
// 2. 采用.class方法获取类的Class对象
Class clazz1 = ReflectTest.class;
System.out.println("clazz1:" + clazz1);
// 3. 采用getClass方法获取类的Class对象
ReflectTest reflectTest = new ReflectTest();
Class clazz2 = reflectTest.getClass();
System.out.println("clazz2:" + clazz2);
// 4. 判断Class对象是否相同
System.out.println("Class对象是否相同:" + ((clazz.equals(clazz1)) && (clazz1.equals(clazz2))));
//不同类加载器加载的同一个类,也会获取不同的Class对象
// 自定义类加载器
ClassLoader myLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
if (is == null) {
return super.loadClass(name);
}
byte[] byteArray = new byte[is.available()];
is.read(byteArray);
return defineClass(name, byteArray, 0, byteArray.length);
} catch (IOException e) {
throw new ClassNotFoundException(name);
}
}
};
// 采用自定义类加载器加载
Class clazz3 = Class.forName("com.zhq.test.ReflectTest", true, myLoader);
// clazz与clazz3并不相同
System.out.println("Class对象是否相同:" + clazz.equals(clazz3));
ps:三种方式获取的Class对象相同的前提是使用了相同的类加载器,Java默认采用应用程序类加载器(sun.misc.Launcher$AppClassLoader)。不同类加载器加载的同一个类,也会获取不同的Class对象