什么是反射
在运行时
才知道要操作的类
是什么,并且可以在运行时
获取类的完整构造
,并调用对应方法
。
反射的缺点
因为反射是运行时动态的去创建类的对象,所以运行效率上必然比直接创建对象要慢。
为什么使用反射
当我们不知道要初始化的类对象是什么但又需要创建类对象时候。
使用场景
1.突破私有权限修饰符的约束限制。(须小心使用
)
2.写框架代码的时候经常需要用。
3.阅读源码。
如何使用反射
- 首先我们先了解类
每个类都是java.lang.Class类的对象,而类的方法、属性和构造函数也都是相应的类(Method类、Field类、Constructor类)。
创建一个Demo类,以便理解使用
public class Demo {
String str;
private int number;
public Demo() {
}
public Demo(String str, int number) {
this.str = str;
this.number = number;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
System.out.println("str");
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
System.out.println("number");
}
private void priMethod(){
System.out.println("priMethod");
}
}
①获取Class对象
- 有三种方式
Demo demo = new Demo();
//1
Class test = Demo.class
//2
Class test = demo.getClass();
//3
Class test = Class.forName("全限定名");
//全限定名指包名+类名
,通常我们都采用方式三进行反射。
②获取类的实例
Demo demo = (Demo) test.newInstance();
③获取构造方法
Class<Demo>clazz = (Class<Demo>)Class.forName("包名+Demo");
//获取全部Constructor对象
Constructor<Demo> [] constructors = (Constructor<Demo>
[])clazz.getConstructor();
//获取带参数的构造方法
Constructor<Demo> constructor = clazz.getConstructor(String.class,int.class);
注意:获取带参数的构造方法时不需要进行转型
通过有参数的构造拿到对象实例
Demo demo = constructor.newInstance("Demo",1);
④获取方法
获取clazz对应类中的所有方法
,包括从父类继承来的所有方法
,但不能获取private修饰的方法
//获取clazz对应类中的所有方法,包括从父类继承来的所有方法,但不能获取private方法
Method [] methods = clazz.getMethods();
如果只获取当前类的方法
,并包含私有方法
,则使用getDeclareMethods即可。
Method [] methods = clazz.getDeclareMethods();
如果只获取指定方法
,若方法有参数
则需要参数名称和参数列表
,无参就不需要写
了。
注意:与获取构造方法一样,带参方法也不需要转型
Method methodStr = clazz.getDeclaredMethod("setStr",String.class);
Method methodInt = clazz.getDeclaredMethod("setNumber",int.class);
⑤获取变量
获取clazz对应类中的所有变量
,包括父类的变量
,但不能获取private修饰的变量
//获取clazz对应类中的所有变量,包括父类的所有变量,但不能获取private变量
Field [] fields = clazz.getFields();
如果只获取当前类的变量
,并包含私有变量
,则使用getDeclaredFields即可。
Field [] fields = clazz.getDeclaredFields();
如果只获取指定变量
,需要传入变量的名字
。
Field fieldStr = clazz.getDeclaredField("str");
⑥获取并执行方法
非私有方法
调用时采用method.invoke(类的实例)
方法,传入②或③步拿到的类的实例
,和方法需要的参数
即可。
methodInt.invoke(demo,1);
私有方法
调用时,须在method.invoke(类的实例)方法前
,调用method.setAccessible(true);
方法。
Method methodPriMethod = clazz.getDeclaredMethod("priMethod");
methodPriMethod.setAccessible(true);
methodPriMethod.invoke(demo);
⑦获取变量的值并设置值
注意:与私有方法一样,若想获取私有变量的值
,需先写field.setAccessible(true);
方法。
Demo demo = new Demo("str",1);
fieldStr.get(demo);
fieldStr.set(demo,"test");
到这里反射的全部用法和概念就记录完成了,这个系列会持续进行更新,如果你觉得对你有帮助,不想错过更新,可以点赞关注。
最后送一句话给自己也与各位共勉
网友评论