什么是反射

将类的各个组成部分封装成其他的对象,就是反射机制

示例代码地址

java代码在计算机中经历的三个阶段

image.png

source源代码阶段

  • 我们编写的都是.java文件
  • 经过java编译器编译后编程了.class文件,.java.class都是在计算机硬盘中的文件

Class类对象阶段

  • .class可以文件可以经过类加载器加载进内存,并且在内存中创建一个Class类对象来表示这个 .class文件的一些共有的特性
  • .class字节码文件中含有成员变量构造方法以及成员方法,而且每一种可能有多个,所以将 每一种类型的数据都定义了一种类型来对应,并且在Class类对象中使用对应的数组来存储
    • 成员变量———>Filed
    • 构造方法———->Constructor
    • 成员方法————>Method

Runtime运行时阶段

在内存中使用Class类对象来表示一个字节码文件后,我们就可以使用这个 Class类对象来创建对象,这就是运行时状态表现出来的。

获取Class类对象

从上面的图可以 知道,要想使用反射,首先要获取的就是Class类对象,而java代码在计算机中三个阶段,在每一个阶段都有对应的获取方式。

Class.forName(源代码阶段)

在源代码阶段,class字节码文件还是在硬盘中,没有被加载进内存,所以此时想要获取Class类对象,可以通过Class.forName("完整类路径")方式获取

  1. package example.classobject;
  2. public class ClassObject {
  3. public static void main(String[] args) throws ClassNotFoundException {
  4. // 第二种方式
  5. Class<?> aClass = Class.forName("example.classobject.ClassObject");
  6. }
  7. }

类名.class(Class类对象阶段)

如果是已经加载进入内存了,那么就可以通过类名.class属性来获取

  1. package example.classobject;
  2. public class ClassObject {
  3. public static void main(String[] args) throws ClassNotFoundException {
  4. // 第一种方式
  5. Class<?> aClass = Class.forName("example.classobject.ClassObject");
  6. // 第二种方式
  7. Class<ClassObject> testOneClass = ClassObject.class;
  8. System.out.println(aClass == testOneClass); // true
  9. }
  10. }

对象.getClass(运行时阶段)

如果已经有了对象,那么就可以通过对象.getClass获取

  1. package example.classobject;
  2. public class ClassObject {
  3. public static void main(String[] args) throws ClassNotFoundException {
  4. // 第一种方式
  5. Class<?> aClass = Class.forName("example.classobject.ClassObject");
  6. // 第二种方式
  7. Class<ClassObject> testOneClass = ClassObject.class;
  8. System.out.println(aClass == testOneClass); // true
  9. // 第三种方式
  10. ClassObject classObject = new ClassObject();
  11. Class<? extends ClassObject> aClass1 = classObject.getClass();
  12. System.out.println(aClass1 == aClass);
  13. }
  14. }

Class对象的功能

上面给出了三种获取Class对象的方法,既然已经获取了Class对象,那么接下来的就是要使用Class对象了,下面列举的是Class对象常用的一些方法。

下面的三组方法都有分为带有Declared的和不带有的,区别在于:

  • 带有Declared可以不用考虑修饰符权限问题
  • 不带有Declared只能操作public修饰符修饰的内容

获取成员变量

带有Declared的,不考虑修饰符所有的成员变量都可以获取

image.png

成员变量的作用

上面的四个方法是获取成员变量,那我们获取了成员变量之后一般都是有两个操作

  • 设置值(下面只是列举一个方法,其余方法可以查看api

    1. void set(Object obj, Object value);
  • 获取值

    1. Object get(Object obj);

获取构造方法

image.png

构造方法的作用

构造器的主要作用就是为了创建对象,主要是使用Constructor对象的newInstance方法,具体用法看上面给的案例地址。

获取成员方法

image.png

成员方法的作用

上面的几个方法是为了获取成员方法,获取成员方法的作用其实就是为了可以执行方法,此时需要使用Method类中的invoke方法,该方法第一个参数是一个实际需要执行的对象,第二个参数是一个可变参数列表。