定义
Java 反射机制在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种 动态的获取信息 以及 动态调用对象的方法 的功能称为 java 的反射机制。
- 反射允许我们可以在程序运行时加载和使用编译期间完全未知的.class文件,就是在运行的时候才知道名称的class文件,然后才知道他的完整构造,生成对象实体,调用方法等等
1 | // 根据路径找到类 |
优缺点
- 可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中。比如,一个大型的软件,当这个程序编译后,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
步骤
注意一定要在try/catch中执行代码
1 | Class clz = Class.forName("com.reflect.api.Apple"); |
获取类的Class对象实例
根据Class对象获取Constructor对象
根据newInstance方法获取反射的对象
如果要调用某一个方法,就需要:
获取方法的Method
利用invoke调用方法(传入反射得到的对象Object)
常用API
- 获取Class对象
1 | Class clz = Class.forName("java.lang.String"); |
- 创建Object对象
1 | Apple apple = (Apple)clz.newInstance(); |
- 获取类属性
1 | Class clz = Apple.class; |
- 获取类的所有方法,用methods替换上面的Fields,获取单个方法的时候使用getMethod或者getDeclaredMethod,并且在后面括号加上方法名,传入参数的类型.class,
注意:如果是私有方法,需要调用setAccessible(true),私有属性同理
举例:
1 | <bean class="com.reflect.Apple"></bean> |
Spring 便会在启动的时候利用反射去加载对应的 Apple 类。而当 Apple 类不存在或发生启发异常时,异常堆栈便会将异常指向调用的 invoke 方法。
Invoke()方法解析
注意看源码
代理模式,三个MethodAccessor实现类,Delegating,Native以及无前缀的MechodAccessorImpl
代码先判断是否存在对应的 MethodAccessor 对象,如果存在那么就复用之前的 MethodAccessor 对象
如果不存在就调用acquireMethodAccessor,调用reflectionFactory对象 的 newMethodAccessor 方法生成一个 MethodAccessor 对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
private MethodAccessor acquireMethodAccessor() {
// First check to see if one has been created yet, and take it
// if so
MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor();
if (tmp != null) {
methodAccessor = tmp;
} else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
}
return tmp;
}先返回的是reflectionFactory生成的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
public MethodAccessor newMethodAccessor(Method var1) {
checkInitted();
if (noInflation && !ReflectUtil.isVMAnonymousClass(var1.getDeclaringClass())) {
return (new MethodAccessorGenerator()).generateMethod(var1.getDeclaringClass(), var1.getName(), var1.getParameterTypes(), var1.getReturnType(), var1.getExceptionTypes(), var1.getModifiers());
}
else {
NativeMethodAccessorImpl var2 = new NativeMethodAccessorImpl(var1);
DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2);
var2.setParent(var3);
return var3;
}
}最终是DelegatingMethodAccessorImpl调用invoke方法,然后再进入其代理的NativeMathodAccessorImpl的Invoke方法
1
2
3
4
5
6
7
8
9
10
11
12
13public MethodAccessor newMethodAccessor(Method var1) {
checkInitted();
if (noInflation && !ReflectUtil.isVMAnonymousClass(var1.getDeclaringClass())) {
return (new MethodAccessorGenerator()).generateMethod(var1.getDeclaringClass(), var1.getName(), var1.getParameterTypes(), var1.getReturnType(), var1.getExceptionTypes(), var1.getModifiers());
}
else {
NativeMethodAccessorImpl var2 = new NativeMethodAccessorImpl(var1);
DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2);
var2.setParent(var3);
// 返回的DelegatingMethodAccessor
return var3;
}
}进入 DelegatingMethodAccessorImpl 类的 invoke 方法后,这里调用了 delegate 属性的 invoke 方法,它又有两个实现类,分别是:DelegatingMethodAccessorImpl 和 NativeMethodAccessorImpl
这里的 delegate 其实是一个 NativeMethodAccessorImpl 对象,所以这里会进入 NativeMethodAccessorImpl 的 invoke 方法。
1
2
3
4public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
return this.delegate.invoke(var1, var2);
}超过该阀值,那么就会生成另一个MethodAccessor 对象,并将原来 DelegatingMethodAccessorImpl 对象中的 delegate 属性指向最新的 MethodAccessorImpl对象。
1
2
3
4
5public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
MethodAccessorImpl var3 = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
this.parent.setDelegate(var3);
}Native 版本一开始启动快,但是随着运行时间边长,速度变慢。Java 版本一开始加载慢,但是随着运行时间边长,速度变快。正是因为两种存在这些问题,所以第一次加载的时候我们会发现使用的是 NativeMethodAccessorImpl 的实现,而当反射调用次数超过 15 次之后,则使用 MethodAccessorGenerator 生成的 MethodAccessorImpl 对象去实现反射。
总体流程
图源博客园@陈树义

绕过编译检查
在编译的时候,泛型会限制集合内元素类型保持一致,但是在运行期泛型不起作用,那么可以通过反射给一个存放String类型的list,在运行的时候添加int
References
https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.html