2-反射的基本使用

反射

一、前言

反射是一种动态依赖机制,其作为各种 java 框架的核心,在 java 中具有举足轻重的地位。集多身优点的它,也因为动态加载而会损耗一定的性能。

其基本使用步骤可分为

  • 1.获取 Class 对象
  • 1.1使用 Class 对象获取 file(字段) 对象 对字段进行操作
  • 1.2使用 Class 对象获取 method(方法) 对象 对方法进行调用。
  • 1.3使用 Class 对象获取 constructor 对象对构造器进行调用。

下面来详细说每个步骤的使用方法

一、获取 Class 对象

从大维度上看,获取 Class 对象是从 4 个基本维度出发。

image-20221217213408966

  1. 代码阶段
    1. ==Class.forName(“全路径”)==
    2. 前提:
      1. 已知一个类的全类名
    3. 类是否会被加载 –>是
    4. 场景
      1. 配置文件
  2. 类加载阶段
    1. ==类名.class==
    2. 类是否会被加载 –>否
    3. 场景
      1. 传参
  3. 运行阶段
    1. ==对象.class==
  4. 使用加载器
    1. 对象.getClass.getClassLoader() –》使用类的加载器的load方法进行类的加载
  5. 基本数据类型获得 Class
    1. 基本数据类型.class
  6. 基本数据类型的==包装类==
    1. 包装类.TYPE

二、常用方法

1.Class类

  • static Class forName(String name)
    • 返回指定类名 name 的 Class 对象
  • Object newInstance
    • 调用缺省构造函数,返回该 Class 对象的一个实例
  • String getName()
    • 返回此 Class 对象所表示的实体(类、接口、数组类、基本数据类型等)名称
  • Class[] getInterfaces()
    • 获取此 Class 对象的接口
  • ClassLoader getClassLoader()
    • 获取该类的类构造器
  • Class getSuperclass()
    • 返回表示此 Class 所表示的实体的类的 ==超类的Class==
  • Constructor[] getConstructors()
    • 返回一个包含本类构造器的数组
  • Field[] getDeclaredFields()
    • 返回 Field 对象的一个数组
  • Method getMethod(String name, Class… paramTypes)
    • 返回一个 Method 对象, name为方法名,方法的形参类型的 Class 对像

2.Method

image-20221217221047646

额外的补充

  1. 类名.class 获取 Class 对象时,该类是否加载的问题。

    使用 ==类名.class获取 Class==不会使 该类被加载,jvm 只会对其进行校验。只有在代码中真正用到了类。比如通过反设调用方法或创建对象,那么在这种情况下该类就会被加载。
    例如

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
      System.out.println(nte.class);
    // System.out.println(nte.age);
    Class<nte> nteClass = nte.class;
    Method hi = nteClass.getMethod("hi");
    hi.invoke(null);
    class nte{
    static int age=10;
    static {
    System.out.println("Helloworld");
    }
    public static void hi(){
    System.out.println("hi");
    }
    }
    输出结果

    class com.reflection.homework.nte
    Helloworld
    hi
    第一个nte.class 输出后,静态方法块中的打印才输出,说明 使用 类名.class 时类并不会被加载。