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

Java 反射(Reflection)技术

反射是 Java 提供的一种强大机制,允许程序在运行时(Runtime)动态地获取类的信息、操作类的属性和方法。这种能力使得 Java 程序可以突破编译时的限制,实现更灵活的设计。

一、反射的核心概念

1. 什么是反射

反射是指在程序运行时动态地:

  • 获取类的完整结构(类名、方法、属性、构造器等)

  • 创建对象

  • 调用方法

  • 访问/修改字段值

2. 反射的核心类

  • Class:代表类的实体

  • Field:代表类的成员变量

  • Method:代表类的方法

  • Constructor:代表类的构造方法

二、反射的基本使用

1. 获取Class对象的三种方式

// 1. 通过类名.class
Class<?> clazz1 = String.class;// 2. 通过对象.getClass()
String str = "Hello";
Class<?> clazz2 = str.getClass();// 3. 通过Class.forName()(最常用)
Class<?> clazz3 = Class.forName("java.lang.String");

2. 创建对象

Class<?> clazz = Class.forName("com.example.User");
// 使用无参构造
Object obj1 = clazz.newInstance(); // 已过时,推荐使用下面的方式
Object obj2 = clazz.getDeclaredConstructor().newInstance();// 使用有参构造
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object obj3 = constructor.newInstance("张三", 25);

3. 调用方法

Class<?> clazz = Class.forName("com.example.Calculator");
Object calculator = clazz.newInstance();// 获取方法
Method addMethod = clazz.getMethod("add", int.class, int.class);// 调用方法
Object result = addMethod.invoke(calculator, 10, 20);
System.out.println("结果: " + result); // 输出: 结果: 30

4. 访问字段

Class<?> clazz = Class.forName("com.example.Person");
Object person = clazz.newInstance();// 获取字段(包括私有字段)
Field nameField = clazz.getDeclaredField("name");// 设置可访问(即使是private字段)
nameField.setAccessible(true);// 设置字段值
nameField.set(person, "李四");// 获取字段值
String name = (String) nameField.get(person);
System.out.println(name); // 输出: 李四

三、反射的应用场景

  1. 框架设计:Spring、Hibernate等框架大量使用反射

    • Spring的IoC容器通过反射创建和管理Bean

    • Hibernate通过反射实现ORM映射

  2. 动态代理:AOP编程的基础

  3. 注解处理:运行时通过反射读取注解信息

  4. 工具类开发:如通用的对象属性拷贝工具

  5. IDE功能:代码提示、自动补全等功能使用反射获取类信息

四、反射的优缺点

优点:

  • 灵活性高:可以在运行时动态操作类和对象

  • 扩展性强:可以实现通用框架和组件

  • 突破访问限制:可以访问私有成员

缺点:

  • 性能开销:反射操作比直接调用慢

  • 安全问题:可以绕过访问权限检查

  • 代码复杂度:反射代码可读性较差

  • 破坏封装性:可以访问私有成员,破坏面向对象特性

五、性能优化建议

  1. 缓存Class对象:避免重复获取

  2. 缓存Method/Field对象:避免重复查找

  3. setAccessible(true)只调用一次

  4. 考虑使用MethodHandle(Java7+)

六、反射与泛型

通过反射可以绕过泛型检查:

List<String> list = new ArrayList<>();
list.add("hello");Class<?> clazz = list.getClass();
Method addMethod = clazz.getMethod("add", Object.class);
addMethod.invoke(list, 100); // 添加非String类型System.out.println(list); // 输出: [hello, 100]

反射是Java高级特性中的重要部分,合理使用可以极大增强程序的灵活性,但也要注意其带来的性能和安全问题。

http://www.xdnf.cn/news/7359.html

相关文章:

  • linux安装git
  • 二叉树-模版题单
  • 使用tcs34725传感器和51单片机识别颜色
  • git仓库中.git 文件很大,怎么清理掉一部分
  • 国标GB28181视频平台EasyGBS校园监控方案:多场景应用筑牢安全防线,提升管理效能
  • 【学习笔记】机器学习(Machine Learning) | 第七章|神经网络(2)
  • Rust 学习笔记:错误处理
  • Web 技术与 Nginx 网站环境部署
  • Pycharm 选择Python Interpreter
  • 酒水饮料批发零售商城小程序开发
  • 深入浅出程序设计竞赛(洛谷基础篇) 第十三章 二分查找与二分答案
  • 小米MUJIA智能音频眼镜来袭
  • 如何查看 Ubuntu开机是否需要密码
  • 一键启动多个 Chrome 实例并自动清理的 Bash 脚本分享!
  • 视图+触发器+临时表+派生表
  • 使用Docker部署React应用与Nginx
  • 分组背包问题:如何最大化背包价值?
  • 基于Java在高德地图面查询检索中使用WGS84坐标的一种方法-以某商场的POI数据检索为例
  • 常见提示词攻击方法和防御手段——提示词越狱
  • 专题五:floodfill算法(太平洋大西洋水流问题)
  • 前端加载超大图片(100M以上)实现秒开解决方案
  • 【分治】快速排序
  • lowcoder数据库操作4:显示查询数据表格
  • 加载渲染geojson数据
  • list.forEach(s -> countService.refreshArticleStatisticInfo(s.getId())); 讲解一下语法
  • Blender cycles烘焙贴图笔记
  • Linux 文件(2)
  • JavaScript 中的五种继承方式进行深入对比
  • vue3 vite 项目中自动导入图片
  • Axure疑难杂症:垂直菜单展开与收回(4大核心问题与专家级解决方案)