Java 反射

Java 反射

作用

  • 在运行时判断任意一个对象所属的类
  • 在运行时获取类的对象
  • 在运行时访问Java对象的属性、方法、构造函数

主要的类

java.lang.reflect包下主要类:

  • Field: 表示类中的成员变量
  • Method: 表示类中的方法
  • Constructor: 表示类的构造方法
  • Array: 该类提供了动态创建数组和访问数组元素的静态方法

Class 类

Class 用来表示运行时类型信息的对应类

Class 类只有一个私有的构造函数,只有JVM能够创建Class类的实例

/*
 * Private constructor. Only the Java Virtual Machine creates Class objects.
 * This constructor is not used and prevents the default constructor being
 * generated.
 */
private Class(ClassLoader loader, Class<?> arrayComponentType) {
    // Initialize final field for classLoader.  The initialization value of non-null
    // prevents future JIT optimizations from assuming this final field is null.
    classLoader = loader;
    componentType = arrayComponentType;
}

.class 文件记录了一个 Class 的所有信息,所有的方法、构造函数、字段等等。JVM启动时通过加载 .class 文件到内存中并创建相关对象。

在运行期间,一个类,只有一个与之相对应的Class对象产生

获取Class 对象的三种方式

  • 通过 ObjectgetClass() 方法
public class ReflectTarget {
    public static void main(String[] args) {
        ReflectTarget reflectTarget = new ReflectTarget();
        Class<? extends ReflectTarget> clazz = reflectTarget.getClass();
    }
}
  • 任何数据类型(包括基础数据类型)的静态 class 属性
public class ReflectTarget {
    public static void main(String[] args) {
        Class<ReflectTarget> reflectTargetClass = ReflectTarget.class;
    }
}
  • 通过 Class 类的静态方法 forName(String className)
public class ReflectTarget {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> clazz = Class.forName("demo.ReflectTarget");
    }
}

反射的主要用法

构造一个类,用于测试

public class ReflectTarget{
    //---------构造函数-----------
    //(默认的带参数构造函数)
    ReflectTarget(String str) {
        System.out.println("(默认)的构造方法 s = " + str);
    }

    //无参构造函数
    public ReflectTarget() {
        System.out.println("调用了公有的无参构造方法 。。。");
    }

    //有一个参数的构造函数
    public ReflectTarget(char name) {
        System.out.println("调用了带有一个参数的构造方法,参数值为 " + name);
    }

    //有多个参数的构造函数
    public ReflectTarget(String name, int index) {
        System.out.println("调用了带有多个参数的构造方法,参数值为【目标名】: " + name + " 【序号】" + index);
    }
    //受保护的构造函数
    protected ReflectTarget(boolean n){
        System.out.println("受保护的构造方法 n :" + n);
    }
    //私有的构造函数
    private ReflectTarget(int index){
        System.out.println("私有的构造方法 序号:" + index);
    }

    //**************字段*******************//
    public String name;
    protected int index;
    char type;
    private String targetInfo;
    @Override
    public String toString(){
        return "ReflectTarget [name=" + name + ", index=" + index + ", type=" + type
                + ", targetInfo=" + targetInfo + "]";
    }
    //***************成员方法***************//
    public void show1(String s){
        System.out.println("调用了公有的,String参数的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("调用了受保护的,无参的show2()");
    }
    void show3(){
        System.out.println("调用了默认的,无参的show3()");
    }
    private String show4(int index){
        System.out.println("调用了私有的,并且有返回值的,int参数的show4(): index = " + index);
        return "show4result";
    }
}

获取类的构造方法并使用

  • Constructor[] getConstructors(): 获取所有“公有的”构造方法
  • Constructor[] getDeclaredConstuctors(): 获取所有的构造方法,包括私有、受保护、默认、公有
  • Constructor getConstructor(Class... parameterType): 获取单个公有的构造方法
  • Constructor getDeclaredConstructor(Class... parameterType): 获取某个构造方法,可以是私有、受保护、默认、公有
  • Constructor--> newInstance(Object... initargs): 调用构造方法
public class ConstructorCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Class.forName("demo.reflect.ReflectTarget");
        //1.获取所有的公有构造方法
        System.out.println("**********************所有公有构造方法*********************************");
        Constructor[] conArray = clazz.getConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }
        //2.获取所有构造方法
        System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
        conArray = clazz.getDeclaredConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }
        //3.获取单个带参数的公有方法
        System.out.println("*****************获取公有、有两个参数的构造方法*******************************");
        Constructor con = clazz.getConstructor(String.class, int.class);
        System.out.println("con = " + con);
        //4.获取单个私有的构造方法
        System.out.println("******************获取私有构造方法*******************************");
        con = clazz.getDeclaredConstructor(int.class);
        System.out.println("private con = " + con);
        System.out.println("******************调用私有构造方法创建实例*******************************");
        //暴力访问(忽略掉访问修饰符)
        con.setAccessible(true);
        ReflectTarget reflectTarget = (ReflectTarget) con.newInstance(1);
    }
}

获取类的成员变量并使用

  • Field[] getFields() : 获取所有的公有字段,包括继承自父类的公有字段
  • Field[] getDeclaredFields(): 获取所有字段,包括:私有、受保护、默认、公有,不包括父类的字段。
  • Field getField(String fieldName): 获取某个公有字段
  • Field getDeclaredField(String fieldName): 获取某个字段
  • Field --> set(Object obj, Object value) : 设置字段的值
public class FieldCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class reflectTargetClass = Class.forName("demo.reflect.ReflectTarget");
        //1.获取所有公有的字段
        System.out.println("************获取所有公有的字段********************");
        Field[] fieldArray = reflectTargetClass.getFields();
        for (Field f : fieldArray){
            System.out.println(f);
        }
        //2.获取所有的字段
        System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
        fieldArray = reflectTargetClass.getDeclaredFields();
        for (Field f : fieldArray){
            System.out.println(f);
        }
        //3.获取单个特定公有的field
        System.out.println("*************获取公有字段并调用***********************************");
        Field f = reflectTargetClass.getField("name");
        System.out.println("公有的field name : " + f);
        ReflectTarget reflectTarget = (ReflectTarget)reflectTargetClass.getConstructor().newInstance();
        //4.给获取到的field赋值
        f.set(reflectTarget, "待反射一号");
        //5.验证对应的值name
        System.out.println("验证name : " + reflectTarget.name);
        //6.获取单个私有的Field
        System.out.println("**************获取私有字段targetInfo并调用********************************");
        f = reflectTargetClass.getDeclaredField("targetInfo");
        System.out.println(f);
        f.setAccessible(true);
        f.set(reflectTarget, "13810592345");
        System.out.println("验证信息" + reflectTarget);
    }
}

获取类的成员方法并使用

  • Method[] getMethods() : 获取所有的公有方法,包含父类和Object类的方法
  • Method[] getDeclaredMethods() : 获取所有的成员方法,不包括父类的方法
  • Method getMethod(String name, Class<?>... parameterTypes): 获取单个公有方法
  • Method getDeclaredMethod(String name, Class<?>... parameterTypes): 获取单个成员方法
  • Method --> invoke(Object obj, Object... args): 调用对象的方法
public class MethodCollector {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1、获取Class对象
        Class reflectTargetClass = Class.forName("demo.reflect.ReflectTarget");
        //2、获取所有公有方法
        System.out.println("***************获取所有的public方法,包括父类和Object*******************");
        Method[] methodArray = reflectTargetClass.getMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        //3、获取该类的所有方法
        System.out.println("***************获取所有的方法,包括私有的*******************");
        methodArray = reflectTargetClass.getDeclaredMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        //4、获取单个公有方法
        System.out.println("***************获取公有的show1()方法*******************");
        Method m = reflectTargetClass.getMethod("show1", String.class);
        System.out.println(m);
        //5、调用show1并执行
        ReflectTarget reflectTarget = (ReflectTarget)reflectTargetClass.getConstructor().newInstance();
        m.invoke(reflectTarget, "待反射方法一号");
        //6、获取一个私有的成员方法
        System.out.println("***************获取私有的show4()方法******************");
        m = reflectTargetClass.getDeclaredMethod("show4", int.class);
        System.out.println(m);
        m.setAccessible(true);
        String result = String.valueOf(m.invoke(reflectTarget, 20));
        System.out.println("返回值 : " + result);
    }
}
posted @ 2022-10-21 20:39  油虾条  阅读(22)  评论(0编辑  收藏  举报