什么是反射?
反射(Reflection)主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。在Oracle 官方文档中提到
反射就是程序能够在运行时 检查拥有的方法,属性以及它们相对应的描述符,并且能够动态地调用类的方法、修改类的字段属性/值的一种机制。
也就是说,我们能够在运行时对Java类进行除了显示调用之外的其它方式,而我们的处理是涵盖了三个方面的(此处先忽略Java中的Security的manager,关于Security Manager的内容将会在后面的文章中继续讨论。)。
类本身,我们可以获取类的全名,类所实现的接口,类所继承的父类
类的方法,我们可以获取类中声明的所有方法(公有/私有),并且对它们进行调用。
类的成员变量(公有/私有),我们可以获取类中声明的所有变量,以及这些变量的属性(类型、描述符),并且能够修改这些变量的值
java.lang.reflect
包含了所有与Java反射相关的文件。 下面我们举个反射的例子。
User.java
package reflectionSample;
public class User {
public User(){};
private String name;
}
ReflectionMain.java
package reflectionSample;
import java.lang.reflect.*;
public class ReflectionMain {
public static void main(String args[]) {
try {
Class<?> clazz = Class.forName("reflectionSample.User");
Field nameField = clazz.getDeclaredField("name");
//获取name这个变量的类型全称
System.out.println(nameField.getType().toGenericString());//public final class java.lang.String
//获取name变量的声明全称
System.out.println(nameField.toGenericString()); //private java.lang.String reflectionSample.User.name
//设置User中name的值
User u = new User();
nameField.setAccessible(true);
nameField.set(u, "testName");
System.out.println(nameField.get(u)); //testName
} catch (Exception e) {
e.printStackTrace();
}
}
}
常用的反射APi
在Oracle 官方文档中提到了一些常用的反射api,如下所示。
关于类变量的反射api
class api | 是否返回列表 | 是否返回继承变量 | 是否返回私有变量 |
---|---|---|---|
getDeclaredField() | 否 | 否 | 是 |
getField() | 否 | 是 | 否 |
getDeclaredFields() | 是 | 否 | 是 |
getFields() | 是 | 是 | 否 |
关于类方法的反射api
class api | 是否返回列表 | 是否返回继承方法 | 是否返回私有方法 |
---|---|---|---|
getDeclaredMethod() | 否 | 否 | 是 |
getMethod() | 否 | 是 | 否 |
getDeclaredMethods() | 是 | 否 | 是 |
getMethods() | 是 | 是 | 否 |
关于类构造函数的反射api
class api | 是否返回列表 | 是否返回私有构造函数 |
---|---|---|
getDeclaredConstructor() | 否 | 是 |
getConstructor() | 否 | 否 |
getDeclaredConstructors() | 是 | 是 |
getConstructors() | 是 | 否 |
反射的实际应用
反射最为广泛的用途之一就是动态代理。
下面一篇文章会详细代理模式,以及Java内部动态代理的实现。