当前位置: 首页 > news >正文

Java 基础(十一)反射

Java反射核心笔记|从基础到实战,吃透反射机制

反射是Java语言的核心特性之一,也是实现“动态编程”的关键——它允许程序在运行时获取类的完整结构(构造方法、成员变量、成员方法),甚至能突破访问权限修饰符的限制,操作私有成员。不管是Spring、MyBatis等框架的底层实现,还是自定义动态化功能,反射都是必备技能。本文结合实战代码,梳理反射的核心知识点和实操要点。

一、反射的核心概念

1. 什么是反射?

反射(Reflection)是Java提供的一种机制,使得程序可以在运行期间:

  • 获取任意类的完整信息(类名、构造方法、字段、方法、访问权限等);
  • 操作任意对象的成员(即使是private修饰的私有成员);
  • 动态创建对象、调用方法、修改字段值。

2. 反射的核心思想

Java中所有类的字节码文件(.class)加载后,都会生成一个唯一的Class类对象——反射的所有操作,都是围绕这个Class对象展开的。

二、获取Class类对象的三种方式

想要操作类的成员,第一步必须获取该类的Class对象(同一个类的Class对象全局唯一)。以下是三种核心方式,结合代码示例理解:

方式语法适用场景
全类名加载Class clazz = Class.forName("包名.类名");动态加载类(如配置文件指定类名),需处理ClassNotFoundException
类名.classClass clazz = 类名.class;编译期确定类,类型安全,无需异常处理
对象.getClass()Class clazz = 实例对象.getClass();已有对象实例,需获取其类信息

代码验证(Class对象唯一性)

// 方式1:全类名加载Classclazz1=Class.forName("AA426.Animal");// 方式2:类名.classClassclazz2=Animal.class;// 方式3:对象.getClass()Animalanimal=newAnimal("cat",18,"white");Classclazz3=animal.getClass();// 结果:true、true(同一个类的Class对象唯一)System.out.println(clazz1==clazz2);System.out.println(clazz1==clazz3);

三、反射操作构造方法

构造方法用于创建对象,反射可以获取任意访问权限的构造方法,并创建实例。

1. 获取构造方法的核心API

API作用
getDeclaredConstructors()获取所有构造方法(含private、protected、默认、public)
getConstructors()仅获取public构造方法
getDeclaredConstructor(参数类型...)获取指定参数的构造方法(含私有)

2. 关键操作:创建对象 + 暴力反射

  • 私有构造方法默认无法访问,需通过setAccessible(true)开启“暴力反射”;
  • 创建对象:Constructor.newInstance(构造参数...)(JDK9后替代过时的Class.newInstance())。

实战示例(操作私有构造)

// 获取Student类的Class对象Classclazz=Student.class;// 获取私有无参构造Constructorconstructor=clazz.getDeclaredConstructor();// 开启暴力反射(突破private限制)constructor.setAccessible(true);// 创建Student实例Studentstudent=(Student)constructor.newInstance();// 同理:获取私有有参构造Constructorconstructor2=clazz.getDeclaredConstructor(String.class,Integer.class);constructor2.setAccessible(true);Studentstudent2=(Student)constructor2.newInstance("李四",1002);

四、反射操作成员变量

成员变量(字段)存储对象的状态,反射可读写任意权限的字段,包括静态字段、final字段。

1. 获取字段的核心API

API作用
getDeclaredFields()获取所有字段(含私有、protected、默认、public)
getFields()仅获取public字段
getDeclaredField("字段名")获取指定名称的字段(含私有)

2. 关键操作:读/写字段值

  • 读字段:field.get(对象实例)
  • 写字段:field.set(对象实例, 新值)
  • 私有字段:需setAccessible(true)
  • 静态字段:get/set时对象参数传null(静态字段属于类,不属于实例);
  • final字段:反射可强制修改(需开启暴力反射)。

实战示例(读写字段)

Classclazz=Student.class;Studentstudent=(Student)clazz.getDeclaredConstructor().newInstance();// 1. 操作私有字段nameFieldnameField=clazz.getDeclaredField("name");nameField.setAccessible(true);// 暴力反射nameField.set(student,"张三");// 写值Stringname=(String)nameField.get(student);// 取值System.out.println(name);// 输出:张三// 2. 操作final字段stuIdFieldstuIdField=clazz.getDeclaredField("stuId");stuIdField.setAccessible(true);stuIdField.set(student,1002);// 强制修改final字段System.out.println(stuIdField.get(student));// 输出:1002// 3. 操作静态字段school(对象传null)FieldschoolField=clazz.getDeclaredField("school");schoolField.setAccessible(true);schoolField.set(null,"清华大学");// 静态字段对象传nullSystem.out.println(schoolField.get(null));// 输出:清华大学

五、反射操作成员方法

成员方法实现对象的行为,反射可调用任意权限的方法,包括静态方法、私有方法。

1. 获取方法的核心API

API作用
getDeclaredMethods()获取所有方法(含私有、protected、默认、public)
getMethods()仅获取public方法(含父类继承的public方法)
getDeclaredMethod("方法名", 参数类型...)获取指定方法(含私有)

2. 关键操作:调用方法

  • 调用方法:Method.invoke(对象实例, 方法参数...)
  • 私有方法:需setAccessible(true)
  • 静态方法:invoke时对象参数传null

实战示例(调用方法)

Classclazz=Student.class;Studentstudent=(Student)clazz.getDeclaredConstructor().newInstance();// 1. 调用静态方法showSchool(对象传null)MethodshowSchoolMethod=clazz.getDeclaredMethod("showSchool");showSchoolMethod.invoke(null);// 输出:静态方法执行// 2. 调用私有方法flayMethodflayMethod=clazz.getDeclaredMethod("flay");flayMethod.setAccessible(true);// 暴力反射flayMethod.invoke(student);// 输出:私有自定义方法执行// 3. 调用带参方法(如Animal的show方法)ClassanimalClazz=Animal.class;Animalanimal=(Animal)animalClazz.getDeclaredConstructor().newInstance();MethodshowMethod=animalClazz.getDeclaredMethod("show",String.class);showMethod.invoke(animal,"小花");// 输出:show()

六、反射核心易错点总结

1.Declared关键字的核心区别

  • Declared(如getDeclaredField):无视访问权限修饰符,获取所有成员(私、保、默、公);
  • 不带Declared(如getField):仅获取public成员。

2. 暴力反射(setAccessible(true))的使用场景

仅当操作私有(private)成员(构造、字段、方法)时需要,public/protected/默认权限的成员无需开启。

3. 异常处理

反射相关操作会抛出CheckedException(如NoSuchMethodExceptionIllegalAccessException),需手动捕获或声明抛出。

4. 性能注意事项

反射比直接调用成员的性能略低,可通过缓存Class/Constructor/Method/Field对象优化(如框架中常用缓存池)。

七、反射的应用场景

  • 框架底层:Spring IOC(动态创建Bean)、MyBatis(动态生成SQL映射);
  • 动态代理:AOP的核心实现(如JDK动态代理);
  • 自定义工具:序列化/反序列化、对象拷贝(如BeanUtils);
  • 插件化开发:动态加载外部类,实现功能扩展。

八、总结

反射是Java“动态性”的核心体现,核心逻辑是:获取Class对象 → 定位目标成员(构造/字段/方法) → 按需开启暴力反射 → 操作成员

虽然反射打破了Java的封装性(可能带来安全风险),但它是框架开发、动态化功能的基石。掌握反射的核心API和易错点,能让我们更深入理解Java底层,也能更好地使用和扩展各类框架。

http://www.jsqmd.com/news/710816/

相关文章:

  • SILENTTRINITY:基于Python异步架构的现代C2渗透测试框架解析
  • Windows电脑终极指南:如何用APK安装器直接运行安卓应用
  • 【Python】错误和异常
  • 亲测5款论文降AI工具:AIGC疑似度从90%降到4%实用指南
  • LycheeMemory:高效处理长上下文任务的创新解决方案
  • 星穹铁道跃迁记录分析工具:5分钟掌握抽卡数据可视化
  • Git 命令大全测试
  • 后端全栈轻松写前端!用 Vue,自动生成可维护 React
  • 终极RPG Maker解密工具:如何快速提取游戏资源与项目文件
  • 别再只用filter: blur()了!聊聊backdrop-filter在Vue3音乐播放器项目中的实战应用
  • RAG 工程实践:分块策略、Rerank、混合检索,这些细节决定效果上限
  • 手机电池寿命翻倍秘诀:BatteryChargeLimit智能充电限制器
  • CQ 省集记录
  • MATLAB新手也能搞定:一步步教你用netCDF读取IPIX雷达海杂波数据(附完整代码)
  • 摩尔线程 x 中国移动|国产GPU率先支撑央企大模型,S5000完成九天35B大模型适配
  • 终极生态系统模拟器Ecosim:探索自然选择与进化的视觉盛宴
  • 大语言模型持续学习评估:OAKS框架解析与实践
  • 基于LoRA微调开源大模型,打造专业法律文本生成AI助手
  • 分组过滤:HAVING
  • [Openclaw] OpenClaw v2026.4.21 升级技术摘要
  • 如何提高网站收录?老手常用的自动推送接口配置
  • 下载 | Win10 2021官方精简版,预装应用极少!(4月更新、Win10 IoT LTSC 2021版、适合老电脑)
  • 黑马点评-短信登陆笔记
  • 重构Android界面叙事:从模板使用到设计系统思维的革命
  • 【数据分析页面】
  • 【Python】面向对象之三大特性
  • 20254323 2025-2026-4—27 《Python程序设计》实验三报告 - Moonshot-_
  • Windows Defender完全移除终极指南:一键彻底卸载系统安全组件的完整解决方案
  • 终极指南:MAA明日方舟自动化助手 - 全功能详解与高效配置教程
  • Swin-UNet实战避坑指南:从论文复现到ACDC数据集心脏分割