什么是反射?
为什么要用反射?
- 实例化对象用new关键字,但是这样就把实例化的工作固定在程序中,不灵活会出现各种问题。
- 反射可以将创建对象的时机从编译时延迟到程序运行时
- 当添加新的功能时,如果不用反射将需要修改代码,修改完需要重新上线非常麻烦,而用反射则没有这个问题
14.2 Class对象
在程序运行时,Class对象保存了类和对象的具体信息。 每个类都有一个Class对象,每当编译一个类,即.java编译成.class文件,就会产生一个Class对象保存在.class文件中
类加载器:
java程序在运行之前并非完全加载:
- **第一次使用这个类,就动态加载到JVM中。当创建第一个对类的静态成员的引用或者构造器时就会加载这个类
类加载器工作步骤:
- 首先检查一个类的Class对象(或理解.class文件)是否已被加载
- 如果尚未加载,默认的类加载器就会根据类名查找.class文件
- 一旦Class对象(.class文件)被加载了(载入jvm),它就被用来创建这个类的所有对象
获取Class对象的引用
**Class对象 = Class.forName("..." )**
可以返回指定Class对象的引用,并且若指定的类没有被加载,就加载它 如果没有Class对象,可以用forName获取。如果已经有一个Class对象,则可以用getClass()
方法获取Class引用
Class常用方法
- Class.forName(“Class path”) 获取指定Class对象
- Class对象.newInstance() 使用默认构造器构造对象
- Class对象.getConstructor() 获取指定的 public修饰构造方法 Constructor对象
- Class对象.getMethod() 获取指定的 public修饰方法 Method对象
- Class对象.getField() 获取指定的 public修饰成员变量 Field对象
使用带参构造方法创建对象(反射)
Class class对象 = Class.forName(" Class路径 ");
Constructor constructor = class对象.getConstructor(new Class[]{ //通过构造器的参数获取构造器对象
//带参构造器的参数
String.class , Float.class,...
});
E 类的对象 = (E) constructor.newInstance(new Object[]{ //通过构造器对象
//传递参数给带参构造器
"...",...,"...",...
});
使用反射调用方法
Class class对象 = Class.forName(" Class路径 ");
Method method = class对象.getMethod("方法名",new Class[]{
//构造器的参数
String.class , Float.class,...
}); //通过方法名和方法的参数获取方法并返回方法对象
method.invoke(类的对象,参数...);//通过哪个类的对象调用这个方法以及方法参数来执行方法
使用反射获取成员对象
获取到成员对象后可以通过get或者set获取数据或修改数据
Class class对象 = Class.forName(" Class路径 ");
Field field = class对象.getField("成员对象名"); // 通过变量名获取成员对象
print(field.get(类的对象)); // 通过哪个类的对象获取变量
field.set(类的对象,需要修改的值); //修改变量
如果要获取非public则都采用getDeclaredXXX
**