反射,是指在运行状态动态获取新的或动态调用对象方法的功能。
使用场景:需要调用私有的属性、方法。我们的对象是不能调用其私有的属性或方法的,但在一些特定的场景,我们又需要使用其属性或者方法,那这时候反射就派上用场了。比如有时候我们会引入第三方的SDK ,但我们是没有其源码的。有一天我们发现需要调用其中的一个私有方法去做点事情(至于做什么事请自行脑补)。
我们来模拟一个这样的场景,首先新建一个类:
public class MyClass {
private int a;
private int b;
private int add(){
return a+b;
}
}
可以看到这个类的属性、方法都为私有的,也就是说就算我们创建了对象,但什么都不能做。现在我们想在使用过程中为 a、b进行赋值,然后调用 add方法。
那么现在有几个问题需要我们解决:
1、如何获取到属性并赋值
2、如何获取到方法并调用
既然有了问题那么我们按照问题来解决了不就可以达到我们的目的了么,燃烧吧...骚年!
通过反射来获取类:
//获取类
Class c = ("");
获取所有的属性并输出:
//获取所有属性
Field[] fields = ();
StringBuffer sb = new StringBuffer();
((())+" class "+()+"{\n");
for (Field field : fields){
("\t");
//获取属性修饰符
((())+" ");
//获取属性类型名称
(().getSimpleName()+" ");
//获取属性名称
(()+";\n");
}
("}\n");
我们可以得到以下的日志输出:
public class MyClass{
private int a;
private int b;
}
噢噢,这不是就拿到了属性了么,so easy!
我们接着在来获取所有的方法并输出:
//获取所有的方法
Method[] methods = ();
for (Method method : methods){
//获取所有方法的参数
Parameter[] parameters = ();
String params = "";
if( > 0){
for (Parameter parameter : parameters){
params += ().getSimpleName()+" "+()+",";
}
params = (0,()-1);
}
((())+" ");
(().getSimpleName()+" ");
(());
("("+params+")\n");
}
得到如下输出结果:
private int add()
到这里,是不是感觉世界是如此的美好,我们提出的问题马上就要解决了。别急,不是还没调用么,继续。
//获取MyClass实例
MyClass myClass = (MyClass) ();
//得到属性a
Field a = ().getDeclaredField("a");
//得到属性b
Field b = ().getDeclaredField("b");
//当为私有时,需设置为true才可调用
(true);
(myClass,1);
(true);
(myClass,2);
Method add = ().getDeclaredMethod("add",null);
(true);
int res = (int)(myClass,null);
每一步都有注释,最终得到的结果为3,符合我们的预期。
这里只是举个例子来做反射调用的举例,实际场景肯定会比这个复杂。但理论上都可以这样去调用,但请注意人家设计为私有肯定是有其道理的,你反射调用去修改了其中的属性,是否会引起别的问题就请君斟酌了。但至少我们不会别一个private难倒了吧!