反射的基本应用

本文介绍了Java反射机制的基本概念和应用,包括类的加载、初始化,以及如何通过反射获取和操作类的构造方法、成员方法和字段。通过反射,可以在运行时动态地获取类信息并执行相关操作,如调用私有方法和字段。文章强调了Class对象的重要性,并提供了知识储备和实际操作示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原理:反射首先是能够获取到Java中的反射类的字节码,然后将字节码中的方法,变量,构造函数等映射成 相应的 Method、Filed、Constructor 等类
应用:取出类的modifiers,数据成员,方法,构造器,和超类
找出某个接口里定义的常量和方法说明.
取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做到.
在运行时刻调用动态对象的方法.

1,类的加载

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实
现对这个类进行初始化。

  • 加载 就是指将 class 文件读入内存,并为之创建一个 Class 对象。 任何类被使用时系统都会建立一个 Class 对象
  • 连接 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数据中的符号引用替换为直接引用
  • 初始化
1.2类的初始化
  1. 创建类的实例
  2. 类的静态变量,或者为静态变量赋值
  3. 类的静态方法
  4. 使用反射方式来强制创建某个类或接口对应的 java.lang.Class 对象
  5. 初始化某个类的子类
1.3反射概述

Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称 为 java 语言的反射机制。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖这个类,使用的就是 Class 类中的方法,所以先要获取到每一个字节码文件所对应的 Class 类型对象。

1.4准备数据,我就用我现在的写的项目的数据,大家随意

在这里插入图片描述

1.5 知识储备

需要掌握 6 个单词

  • Class 类
  • Constructor 构造
  • Method 方法
  • Filed 字段
  • instance 实例
  • invoke 执行
1.6 Class 获得方式

在这里插入图片描述

public class A {
    /**
     * class获得方式
     *
     * @param args
     */
    public static void main(String[] args) {
        //1 通过类型获得
        // 语法:类名.class
        // 应用场景:确定类型 等
        Class clazz1 = BrandController.class;
        System.out.println("语法:类名.class|" + clazz1);

        //2 通过实例对象获得
        // 语法:变量.getClass()
        // 应用场景:在方法内部通过参数获得类型 等
        BrandController brandController = new BrandController();
        Class<? extends BrandController> aClass = brandController.getClass();
        System.out.println("语法:变量.getClass()|" + aClass);


        //3 通过字符串获得
        // 语法:Class.forName("全限定类名")
       // 应用场景:通过配置获得字符串 等
        try {
            Class<?> aClass1 = Class.forName("com.controller.BrandController");
            System.out.println("Class.forName(\"全限定类名\")|"+aClass1);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }


}

1.6.1 得到这个类的名字

在这里插入图片描述

      //1 获得 Class
       Class clazz = User.class;
       // 得到这个类的名字:全限定类名
        String name = clazz.getName();
        //  这个只是类的名字
        String simpleName = clazz.getSimpleName();
        System.out.println(" 这个只是类的名字simpleName:"+simpleName);

        System.out.println("得到这个类的名字:全限定类名name:"+name);




1.7构造方法与实例

在这里插入图片描述

public class A {
    /**
     * 构造方法与实例
     *
     * @param args
     */
    public static void main(String[] args) {
        //无参构造 , 并实例化

        //1 获得 Class
        Class<SpecificationOption> specificationOptionClass = SpecificationOption.class;
        System.out.println("获得 Class"+specificationOptionClass);
        //2 获得构造 -- 没有形参
        Constructor<SpecificationOption> constructor = null;
        try {
            constructor = specificationOptionClass.getConstructor();
            System.out.println("获得构造 -- 没有形参"+constructor);
            SpecificationOption specificationOption = constructor.newInstance();
            System.out.println("实例对象,没有实参"+specificationOption);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
获取无参的简化版

在这里插入图片描述


public class A {
    /**
     * 构造方法与实例
     *
     * @param args
     */
    public static void main(String[] args) {
        //无参构造 , 并实例化

        //1 获得 Class
        try {
            // 获得无参的简化版
            SpecificationOption specificationOption = SpecificationOption.class.newInstance();
            System.out.println(specificationOption);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }


    }
}
获取有参构造

在这里插入图片描述
在这里插入图片描述

public static void main(String[] args) {
        //有参构造 , 并实例化
        //1 获得 Class
        Class beanClass = SpecificationOption.class;
        //2 获得构造 -- 三个字符串形参 -- (Integer.class,String.class,Integer.class)
        Constructor constructor = null;
        try {
            constructor = beanClass.getConstructor(Integer.class, String.class, Integer.class);
            System.out.println("获得构造 -- 三个字符串形参" + constructor);
            //3 实例对象,三个字符串实参
            Object o = constructor.newInstance(2323,"白色", 1);
            System.out.println(o);
        } catch (Exception e) {
            e.printStackTrace();

        }

    }
1.7.5 扩展:私有构造(暴力反射)
  • 修改 Bean 添加私有构造
private Bean(String id) {
this.id = id;
System.out.println("有参构造:" + id);
}
  • getConstructor() 使用该方法将无法获得私有方法,程序运行抛异常
  • 在这里插入图片描述
  • 没有使用 setAccessible(true),将抛异常
  • 在这里插入图片描述
    在这里插入图片描述
@Test
public void testPrivateCons() throws Exception{
//私有构造
//1 获得 Class
Class beanClass = Bean.class;
//2 获得构造 -- 两个字符串形参 -- Bean(String id, String className)
// * getConstructor() 将抛异常 java.lang.NoSuchMethodException
// * getDeclaredConstructor 可以获得私有构造
Constructor constructor = beanClass.getDeclaredConstructor(String.class)
//暴力访问
constructor.setAccessible(true);
//3 实例对象,两个字符串实参
Object bean = constructor.newInstance("userId");
System.out.println(bean);

1.8方法与执行
1.8.1public 方法
  • 获得方法并设置
    在这里插入图片描述
  //1 获得 Class
        Class clazz = User.class;
        //2 获得实例 ,相当于 Object obj = new Bean();
        Object obj = clazz.newInstance();
        //3 操作 setAge 方法
        // * 格式:getMethod(方法名,形成列表)
        Method setMethod = clazz.getMethod("setAge", Integer.class);

        System.out.println("getMethod(方法名,形成列表)"+setMethod);
        //3.2 执行方法,一个实参
        Object setReturnObj = setMethod.invoke(obj, 12);
        System.out.println("set 方法返回值:" + setReturnObj);

1.8.2私有方法(暴力反射)private

添加私有方法
在这里插入图片描述

在这里插入图片描述


        //4 操作 getId 方法
        // 4.1 获得方法,没有形参
        Method getMethod = clazz.getMethod("getAge");
        // 4.2 执行方法,没有实参
        Object getReturnObj = getMethod.invoke(obj);
        System.out.println("get 方法返回值:" + getReturnObj);


         //5 暴力反射私有的构造方法
        Method showMethod = clazz.getDeclaredMethod("show");
        System.out.println("暴力反射私有的构造方法show     "+showMethod);
         //暴力访问
        showMethod.setAccessible(true);
          // 4 执行方法,没有实参
        // obj.setMethod(args)     user.setAge(20)
        Object invoke = setMethod.invoke(obj, 20);
        Object result = showMethod.invoke(obj);
        System.out.println("show私有"+result);
1.8.3 main 方法与执行

添加main方法
在这里插入图片描述

在这里插入图片描述

 //有参构造 , 并实例化
        Class<User> clazz = User.class;
        //2 获得方法 -- main 静态方法 -- public static void main(String[] args)
        Method mainMethod = clazz.getMethod("main", String[].class);
        Object getReturnObj =  mainMethod.invoke(null, (Object)new String[]{"aaa","bbb"});
        System.out.println("main 方法返回值:|||||||||" + getReturnObj);
1.8.4 public 字段的操作

在这里插入图片描述


  //5 操作字段,进行赋值,public String  name;
        //5.1 获得的字段,一个形参
        // * 格式:getField(字段名)
        Field descriptionField = clazz.getField("name");
        System.out.println("getField(字段名)     "+descriptionField);

        //5.2 为对象的字段赋值
        descriptionField.set(obj, "喜欢在文字中倾诉");

        //5.3 获取对象的字段值
        Object fieldReturnObj = descriptionField.get(obj);
        System.out.println("description 字段返回值:       "+fieldReturnObj);


1.8.5 private 字段的操作

在这里插入图片描述

在这里插入图片描述

   //5 操作字段,进行赋值,private String  name;
        //5.1 获得的字段,一个形参
        // * 格式:getDeclaredField(字段名)
        Field descriptionField = clazz.getDeclaredField("name");
        System.out.println("getDeclaredField(字段名)     "+descriptionField);
        //暴力访问
        descriptionField.setAccessible(true);
        //5.2 为对象的字段赋值
        descriptionField.set(obj, "喜欢在文字中倾诉");

        //5.3 获取对象的字段值
        Object fieldReturnObj = descriptionField.get(obj);
        System.out.println("description 字段返回值:       "+fieldReturnObj);

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值