反射--java

本文详细阐述了Java程序如何通过类加载器加载Class文件,验证并初始化类的过程,以及三种获取字节码文件的方式。重点介绍了通过字节码反射获取构造方法和成员变量的技术,包括无参和有参构造,以及通过Field读写对象属性的应用示例。
摘要由CSDN通过智能技术生成

1.过程

  • 加载

    • 把class文件加载到内存(通过类加载器),转为二进制数据
    • 生成一个java.lang.Class的对象,作为方法区访问这个类的入口
  • 链接

    • 验证 : 主要进行正确性的校验(class文件) cafe babe “咖啡宝贝” 魔法数字

    • 准备:给类的静态成员分配内存,赋默认值

      • static int a = 10;
        
    • 解析: 把符号引用替换为直接引用(真实的内存地址)

  • 初始化

    • 执行静态代码块中的内容, 静态成员赋真实的值
      在这里插入图片描述
      在这里插入图片描述

2.获取字节码文件的3种方式

  • 对象.getClass()
  • 类名.class
  • Class.forName(“全类名”)

配置文件(Properties)

配置文件里面一般放配置信息 , 数据库配置信息, 第三方服务的配置信息(账号信息 )
比如使用一个软件时,将其用户和密码放置到配置文件中

在这里插入图片描述
Properties

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串

构造方法

Properties() 创建一个无默认值的空属性列表。

成员方法

voidload(InputStream inStream) 从输入流中读取属性列表(键和元素对)。
voidload(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
StringgetProperty(String key) 用指定的键在此属性列表中搜索属性。

注意:

  • 如果有中文 , 使用load(Reader reader)
  • 注释使用#

3.字节码的运用

1.通过字节码反射获取类的构造方法

/*
 *
 * @author:alia
 * @DATA : 2023/3/2112:09
 *
 * 通过反射获取Person这个类的构造方法
 */
public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //通过字节码文件对象获取信息
        Class<?> personClass = Class.forName("_23Reflect.Person");
        System.out.println("获取所有的public构造方法");
        Constructor<?>[] constructors = personClass.getConstructors();
        for (Constructor c:constructors){
            System.out.println(c);
        }
        System.out.println("------------------------");
        //获取全部构造方法
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        for (Constructor c:declaredConstructors){
            System.out.println(c);
        }
        //获取无参构造方法(条件获取
        Constructor<?> constructor = personClass.getConstructor();
        //获取有参构造方法
        Constructor<?> constructor1 = personClass.getConstructor(String.class, int.class, boolean.class);
        Constructor<?> declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class);

        //使用构造方法创建对象
        System.out.println("使用构造方法创造对象");
        Object o = constructor.newInstance();
        System.out.println(o);

        //通过该方法设置后,可以使用私有构造方法创造对象
        declaredConstructor.setAccessible(true);

    }
}

2.通过字节码反射获取成员变量

通过反射获取所有成员变量

Field[] getFields()
Field[] getDeclaredFields()

获取指定成员变量

Field getField(String name)
Field getDeclaredField(String name)

通过Field读写对象的成员变量(可暴力破解)
Object get(Object obj):获取值,传入对象
void set(Object obj, Object value):赋值,传入对象

public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取字节码文件对象
        Class<?> personCls = Class.forName("com.cskaoyan.domain.Person");
        System.out.println("获取所有的带public的成员变量------");
        // Field[] getFields()
        Field[] fields = personCls.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }

        System.out.println("获取所有的成员变量------");
        //Field[] getDeclaredFields()
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field f : declaredFields) {
            System.out.println(f);
        }
        System.out.println("获取指定的public的成员变量------");

        // Field getField(String name)
        Field nameField = personCls.getField("name");
        System.out.println(nameField);

        //Field getDeclaredField(String name)
        Field ageField = personCls.getDeclaredField("age");
        Field genderField = personCls.getDeclaredField("gender");
        System.out.println(ageField);
        System.out.println(genderField);

        // 设置 获取成员变量的值
        //void set(Object obj, Object value):赋值,传入对象
        // 先获取构造方法
        Constructor<?> declaredConstructor = personCls.getDeclaredConstructor();
        // 再实例化对象
        Object o = declaredConstructor.newInstance();
        nameField.set(o,"zs");
        System.out.println(o);

        // 忽略语法检查
        ageField.setAccessible(true);
        ageField.set(o,20);
        System.out.println(o);

        // Object get(Object obj):获取值,传入对象
        Object o1 = nameField.get(o);
        System.out.println(o1);
        Object o2 = ageField.get(o);
        System.out.println(o2);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤狐先生

如果有一点点帮助,可以给点支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值