java-反射

反射是什么?:

在日常工作中是用反射的机会不多,使用反射主要是当需要动态操作类的时候以及在框架中使用例如Spring中的依赖注入,JUnit的测试方法调用。
大白话介绍就是:Java 中的 反射(Reflection) 就像给程序一面「照妖镜」,让它能在运行时动态地「看到」自己的结构(比如类、方法、字段等),甚至能调用原本无法直接访问的代码。这种能力让程序变得更灵活,但也会带来性能开销和安全风险。

反射原理:

Java 在编译时会将类的信息(类名、方法、字段、注解等)保存在 .class 文件中。当类被加载到内存时,JVM 会为每个类生成一个唯一的 Class 对象,这个对象就像一个「身份证」,存储了类的所有元数据。反射的本质就是通过 Class 对象去读取和操作这些元数据。
(理解需要一点JVM知识)

能做什么?:

  • 运行时动态获取类的信息
    1. 比如获取类的名称、父类、接口、方法、字段等。
  • 动态创建对象
    1. 即使不知道类名,也能通过字符串构造对象。
  • 调用私有方法或访问私有字段
    1. 突破访问权限限制(需谨慎使用)。
  • 实现通用框架
    1. 比如 Spring 通过反射创建 Bean、JUnit 通过反射调用测试方法。

基本使用:

简化版

第一步:获取class对象

// 1. 通过类名获取
Class<?> clazz = String.class;

// 2. 通过对象获取
String str = "Hello";
Class<?> clazz = str.getClass();

// 3. 通过全类名动态加载(最常用)
Class<?> clazz = Class.forName("java.lang.String");

第二步:操作类

// 创建对象(调用无参构造)
Object obj = clazz.getDeclaredConstructor().newInstance();

// 获取方法并调用
Method method = clazz.getMethod("length");
int length = (int) method.invoke(obj); // 相当于调用 obj.length()

// 访问私有字段(需要解除安全检查)
Field field = clazz.getDeclaredField("value");
field.setAccessible(true); // 突破 private 限制
byte[] value = (byte[]) field.get(obj);

反射的原理细节

  • Class 对象是反射的入口
    1. JVM 在类加载阶段(ClassLoader.loadClass())解析 .class 文件,生成 Class 对象。
  • 元数据存储在方法区
    1. 类的方法、字段等信息存储在 JVM 的方法区(Method Area),反射通过 Class 对象访问这些数据。
  • 反射调用方法的本质
    1. 调用 method.invoke() 时,JVM 底层通过 MethodAccessor 实现,首次调用会生成一个 NativeMethodAccessorImpl(基于本地方法),后续可能生成动态字节码加速(GeneratedMethodAccessor1)。

实际使用场景

  • Spring 框架:通过 @Autowired 动态注入对象。
  • JUnit:通过反射识别并执行 @Test 方法。
  • JSON 序列化工具:将对象的字段名和值动态转换为 JSON 字符串。

总结

反射是 Java 的「自省」能力,通过 Class 对象在运行时探索和操作类的结构。它让代码更灵活,但需谨慎使用——能不用则不用,除非你正在写框架或处理动态逻辑。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

在下陈平安

你的鼓励是我创作最大的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值