反射(Reflect)

  • 概念及作用

    概念:反射(Reflect)是在运行时动态访问类与对象的技术。

    反射是JDK1.2版本后的高级特性,属于java.lang.reflect包下。

    大多数Java框架都基于反射实现参数配置、动态注入等特性。

    用于不修改源代码(静态编译)的情况,程序运行时动态创建对应的方法。

    反射机制根据外部输入的类名找到对应的类中的实现方法,实现动态功能,后续添加其他方法类也不需要修改源代码。

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Scanner sc = new Scanner(System.in);
    System.out.println("请输入计算方法:");
    String op = sc.next();
    System.out.println("请输入第一个数据:");
    Float a = sc.nextFloat();
    System.out.println("请输入第二个数据:");
    Float b = sc.nextFloat();
    try{
    // 反射技术动态创建实现类并进行计算,动态访问类
    MathOpetation mathOpetation = (MathOpetation) Class.forName("com.codewhale.reflect." + op).newInstance();
    float result = mathOpetation.mathOperation(a, b);
    System.out.println("结果:"+result);
    }catch (Exception e){
    e.printStackTrace();
    }
  • 核心类

    • Class类

      Class是JVM中代表“类和接口”的类。

      Class对象具体包含了某个特定类的结构信息。

      通过Class对象可获取对应类的构造方法/方法/成员变量。

      Class核心方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      try {
      // Class.forName方法将指定的类加载到jvm,并返回对应class对象
      Class studentClass = Class.forName("com.codewhale.reflect.Student");
      System.out.println("studentClass已被加载到JVM中");
      // newInstance通过默认无参构造方法创建新的对象
      Student student = (Student)studentClass.newInstance();
      System.out.println(student);
      } catch (ClassNotFoundException e) {
      // 类名与类路径书写错误是抛出"类无法找到"异常
      e.printStackTrace();
      } catch (InstantiationException e) {
      // 非法访问异常,当在作用域外访问对象方法或成员变量时抛出
      e.printStackTrace();
      } catch (IllegalAccessException e) {
      // 对象无法被实例化时抛出
      e.printStackTrace();
      }
    • Constructor构造方法类

    • Method方法类

      Method对象指代某个类中的方法描述。

      Method对象使用classObj.getMethod()方法获取。

      通过Method对象调用指定对象的对应方法。

      Method类核心方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      try {
      Class studentClass = Class.forName("com.codewhale.reflect.Student");
      Constructor constructor = studentClass.getConstructor(new Class[]{
      Integer.class, String.class, Integer.class
      });
      Student student = (Student)constructor.newInstance(new Object[]{
      1, "张三", 22
      });
      Method studentUpdateAge = studentClass.getMethod("updateStudent", new Class[]{
      Integer.class
      });
      Student student1 = (Student) studentUpdateAge.invoke(student, new Object[]{
      30
      });
      System.out.println(student1);
      } catch (NoSuchMethodException e) {
      e.printStackTrace();
      } catch (ClassNotFoundException e) {
      e.printStackTrace();
      } catch (InvocationTargetException e) {
      e.printStackTrace();
      } catch (InstantiationException e) {
      throw new RuntimeException(e);
      } catch (IllegalAccessException e) {
      e.printStackTrace();
      }
    • Field成员变量类

      Field对应某个具体类中的成员变量的声明。

      Field对象使用classObj.getField()方法获取。

      通过Field对象可为某对象成员变量赋值/取值。

      Field类核心方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      try {
      Class studentClass = Class.forName("com.codewhale.reflect.Student");
      Constructor studentConstructor = studentClass.getConstructor(new Class[]{
      Integer.class, String.class, Integer.class
      });
      Student student = (Student)studentConstructor.newInstance(new Object[]{
      1,"张三",25
      });
      Field studentName = studentClass.getField("name");
      System.out.println("原姓名:"+studentName.get(student).toString());
      studentName.set(student, "张一");
      String studentName1 = (String)studentName.get(student);
      System.out.println("更改后的姓名:"+studentName1);
      System.out.println(student);
      } catch (NoSuchMethodException e) {
      e.printStackTrace();
      } catch (ClassNotFoundException e) {
      e.printStackTrace();
      } catch (InvocationTargetException e) {
      e.printStackTrace();
      } catch (InstantiationException e) {
      throw new RuntimeException(e);
      } catch (IllegalAccessException e) {
      e.printStackTrace();
      } catch (NoSuchFieldException e) {
      e.printStackTrace();
      }
    • getDeclared系列方法说明

      getDeclaredConstructor(s)|Method(s)|Field(s)获取对应对象,加s代表获取所有对象

      getConstructor(s)|Method(s)|Field(s)只能获取public对象

      访问非作用域内构造方法、方法、成员变量,会抛出异常。

      getDeclared系列方法可获取private等对象

      • Field类中getModifiers()方法用于判断该成员变量是否为public变量。当结果为1则为public修饰;当结果为2则为private修饰
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      try {
      Class studentClass = Class.forName("com.codewhale.reflect.Student");
      Constructor studentConstructor = studentClass.getConstructor(new Class[]{
      Integer.class, String.class, Integer.class
      });
      Student student = (Student)studentConstructor.newInstance(new Object[]{
      1,"张三",25
      });
      Field[] declaredFields = studentClass.getDeclaredFields();
      for (Field declaredField : declaredFields) {
      if (declaredField.getModifiers() == 1){ // 结果为1则为public修饰
      Object val = declaredField.get(student);
      System.out.println(declaredField.getName()+":"+val);
      }else if (declaredField.getModifiers() == 2){ // 结果为2则为private修饰,则需要使用getXxx()调用。
      String methodName = "get"+declaredField.getName().substring(0, 1).toUpperCase() + declaredField.getName().substring(1);
      Method method = studentClass.getMethod(methodName);
      Object yet = method.invoke(student);
      System.out.println(declaredField.getName()+":" + yet);
      }
      }
      } catch (NoSuchMethodException e) {
      e.printStackTrace();
      } catch (ClassNotFoundException e) {
      e.printStackTrace();
      } catch (InvocationTargetException e) {
      e.printStackTrace();
      } catch (InstantiationException e) {
      throw new RuntimeException(e);
      } catch (IllegalAccessException e) {
      e.printStackTrace();
      }