什么是反射?

反射是在运行时动态访问类和对象的技术

为什么要用反射?

  • 实例化对象用new关键字,但是这样就把实例化的工作固定在程序中,不灵活会出现各种问题。
  • 反射可以将创建对象的时机从编译时延迟到程序运行时
  • 当添加新的功能时,如果不用反射将需要修改代码,修改完需要重新上线非常麻烦,而用反射则没有这个问题

14.2 Class对象

在程序运行时,Class对象保存了类和对象的具体信息。 每个类都有一个Class对象,每当编译一个类,即.java编译成.class文件,就会产生一个Class对象保存在.class文件中

类加载器:

java程序在运行之前并非完全加载:

  • **第一次使用这个类,就动态加载到JVM中。当创建第一个对类的静态成员的引用或者构造器时就会加载这个类

类加载器工作步骤:

  1. 首先检查一个类的Class对象(或理解.class文件)是否已被加载
  2. 如果尚未加载,默认的类加载器就会根据类名查找.class文件
  3. 一旦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对象

使用带参构造方法创建对象(反射)

  1. Class class对象 = Class.forName(" Class路径 ");
  2. Constructor constructor = class对象.getConstructor(new Class[]{ //通过构造器的参数获取构造器对象
  3. //带参构造器的参数
  4. String.class , Float.class,...
  5. });
  6. E 类的对象 = (E) constructor.newInstance(new Object[]{ //通过构造器对象
  7. //传递参数给带参构造器
  8. "...",...,"...",...
  9. });

使用反射调用方法

  1. Class class对象 = Class.forName(" Class路径 ");
  2. Method method = class对象.getMethod("方法名",new Class[]{
  3. //构造器的参数
  4. String.class , Float.class,...
  5. }); //通过方法名和方法的参数获取方法并返回方法对象
  6. method.invoke(类的对象,参数...);//通过哪个类的对象调用这个方法以及方法参数来执行方法

使用反射获取成员对象

获取到成员对象后可以通过get或者set获取数据或修改数据

  1. Class class对象 = Class.forName(" Class路径 ");
  2. Field field = class对象.getField("成员对象名"); // 通过变量名获取成员对象
  3. print(field.get(类的对象)); // 通过哪个类的对象获取变量
  4. field.set(类的对象,需要修改的值); //修改变量

如果要获取非public则都采用getDeclaredXXX
**