【Hutool系列】反射工具-ReflectUtil
前言
反射是 Java 中一种强大的机制,可以在运行时动态地获取类的信息并操作类的属性和方法。在 Java 中,通过反射可以获取和设置类的字段、调用类的方法、创建类的实例等。Java的反射机制,可以让语言变得更加灵活,对对象的操作也更加“动态”,因此在某些情况下,反射可以做到事半功倍的效果。本文将介绍如何使用Hutool中的反射工具类来获取获取类信息、操作字段、调用方法、构造对象等常见功能,并提供了相关的代码示例。
一、概述
1.1 工具简介
Hutool是一个Java工具类库,提供了很多常用的工具类和方法,包括反射操作。通过Hutool,我们可以更加方便地使用反射来获取类的属性值。Hutool针对Java的反射机制做了工具化封装,封装包括获取构造方法、获取字段、获取字段值、获取方法、执行方法(对象方法和静态方法)等。示例如下所示:
// 获取某个类的所有方法
Method[] methods = ReflectUtil.getMethods(PmsBrand.class);
// 获取某个类的指定方法
Method method = ReflectUtil.getMethod(PmsBrand.class, "getId");
// 使用反射来创建对象
PmsBrand pmsBrand = ReflectUtil.newInstance(PmsBrand.class);
// 反射执行对象的方法
ReflectUtil.invoke(pmsBrand,"setId",1);
return CommonResult.success(null,"操作成功!");
1.2 引入依赖
在使用Hutool工具之前,我们需要将Hutool添加到项目的依赖中。如果使用Maven构建项目,可以在 pom.xml 文件中添加以下依赖:
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>${hutool.version}</version>
</dependency>
Hutool-all 是一个 Hutool 的集成打包产品,由于考虑到“懒人”用户及分不清各个模块作用的用户,“无脑”引入 hutool-all 模块是快速开始和深入应用的最佳方式。如果你想像 SpringBoot 一样引入 Hutool,再由子模块决定用到哪些模块,你可以在父模块中加入:
<dependencyManagement><dependencies><dependency><groupId>cn.hutool</groupId><artifactId>hutool-bom</artifactId><version>${hutool.version}</version><type>pom</type><!-- 注意这里是import --><scope>import</scope></dependency></dependencies>
</dependencyManagement>
然后再在子模块中就可以引入自己需要的模块了:
<dependencies><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId></dependency>
</dependencies>
二、基本使用示例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String name;private Integer age;private Boolean gender;
}
2.1 工具类的基本结构
工具类通常由静态方法组成,并且构造函数设为私有以防止实例化,如下所示。
public class ReflectUtil {// 私有构造函数,防止实例化public ReflectUtil() {}
}
2.2 对类的操作
ReflectionUtil 是一个Java反射工具类,它提供了一些简化反射操作的方法。ReflectionUtil 可以获取类的各种信息,比如类名、类的修饰符、类的父类、实现的接口等,这些信息可以通过调用 ReflectionUtil 的方法来获取。
构造对象
通过反射创建对象,包括使用无参和有参构造方法,如下所示。
@Test
public void constructorTest() {// 获取所有构造方法Constructor<User>[] constructors = ReflectUtil.getConstructors(User.class);for (Constructor<User> constructor : constructors) {Console.log("getConstructors->获取构造方法:", constructor);}// 获取无参构造方法Constructor<User> constructor = ReflectUtil.getConstructor(User.class);Console.log("getConstructor->获取无参构造方法:", constructor);// 获取有参构造方法Constructor<User> constructor1 = ReflectUtil.getConstructor(User.class, String.class, Integer.class,Boolean.class);Console.log("getConstructor->获取有参构造方法:", constructor1);String name = constructor1.getName();Console.log("name:{}", name);int modifiers = constructor1.getModifiers();Console.log("modifiers:{}", modifiers);}
创建类实例
ReflectionUtil 可以通过反射来创建对象,它提供了一个newInstance 方法,可以根据类名来创建相应的对象。
@Test
public void newInstanceTest() {ReflectUtil.newInstance(User.class);
}
2.3 对方法的操作
通过反射调用类的方法,包括获取方法和执行方法,ReflectionUtil 同样提供了方法来简化方法的调用,一些儿常用方法如下所示。
// 查找指定方法。如果找不到对应的方法则返回null
Method getMethod(Class<?> clazz, boolean ignoreCase, String methodName, Class<?>... paramTypes);// 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回null
Method getMethodIgnoreCase(Class<?> clazz, String methodName, Class<?>... paramTypes);// 查找指定方法。如果找不到对应的方法则返回null
Method getMethodByName(Class<?> clazz, boolean ignoreCase, String methodName);// 获得指定类中的方法名
Method[] getMethods(Class<?> beanClass);// 调用方法。
T invoke(Object obj, Method method, Object... args) throws InvocationTargetRuntimeException, UtilException;// 执行方法
T invoke(Object obj, String methodName, Object... args) throws UtilException;
T invokeRaw(Object obj, Method method, Object... args) throws InvocationTargetException, IllegalAccessException;// 执行静态方法
T invokeStatic(Method method, Object... args) throws UtilException;// 执行方法,执行前要检查给定参数
T invokeWithCheck(Object obj, Method method, Object... args) throws UtilException;
获取类的方法
/*** 获取某个类的所有方法*/
@Test
public void getMethodsTest() {Method[] methods = ReflectUtil.getMethods(User.class);Arrays.stream(methods).forEach(System.out::println);
}/*** 获取某个类的指定方法*/
@Test
public void getMethodTest() {Method methods = ReflectUtil.getMethod(User.class, "getName");
}
调用方法
ReflectionUtil 可以通过反射来调用类的方法,它提供了 invokeXXXX
方法,可以根据方法名和参数类型来调用相应的方法。
@Test
public void invokeMethodTest() {ReflectUtil.invoke(User.class, "setName", "独泪了无痕");
}
2.4 对属性的操作
ReflectUtil 也简化了对字段的访问操作,可以通过反射来获取对象的字段值,它提供了一个 getFieldValue
方法,可以根据字段名来获取相应的字段值。除此之外,还可以通过反射来设置对象的字段值,提供了一个 setFieldValue
方法,可以根据字段名来设置相应的字段值。
// 查找指定类中的指定name的字段,也包括父类和Object类的字段,字段不存在则返回null
Field getField(Class<?> beanClass, String name);// 获取指定类中字段名和字段对应的有序Map,包括其父类中的字段。
// 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后
Map<String, Field> getFieldMap(Class<?> beanClass);// 获取字段名,如果存在Alias注解,读取注解的值作为名称
String getFieldName(Field field);// 获得一个类中所有字段列表,包括其父类中的字段。
// 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后
Field[] getFields(Class<?> beanClass);// 获取指定对象所有字段的值
Object[] getFieldsValue(Object obj);// 获取字段值
Object getFieldValue(Object obj, Field field);
Object getFieldValue(Object obj, String fieldName);
获取类的属性字段
@Test
public void getFieldsTest() {User user = new User();// 获取实体中所有属性字段Field[] fields = ReflectUtil.getFields(user.getClass());Arrays.stream(fields).forEach(field -> {Console.log("getFields-获取User类的所有字段:", field);Console.log("getFieldName->获取字段名:", ReflectUtil.getFieldName(field));Console.log("getFieldValue->获取字段值:", ReflectUtil.getFieldValue(new User(), field));Console.log("getModifiers->获取字段修饰符:", field.getModifiers());Console.log("getType->获取字段类型:", field.getType());Console.log("获取属性字段类型:", field.getType().getCanonicalName());});
}
获取类的字段值
通过 Hutool 中的 ReflectUtil 类,我们可以获取Java类的字段值,如下所示:
@Test
public void getFieldValueTest() {User user = new User();user.setName("独泪了无痕");user.setAge(30);user.setGender(true);System.out.println("Name:" + ReflectUtil.getFieldValue(user, "name"));System.out.println("Age:" + ReflectUtil.getFieldValue(user, "age"));System.out.println("Gender:" + ReflectUtil.getFieldValue(user, "gender"));
}
在上面的示例中,我们通过 ReflectUtil.getFieldValue()
方法获取了类的字段值。该方法接受两个参数,第一个参数是要获取字段值的对象,第二个参数是字段的名称。
三、总结
ReflectUtils类通过结合Java反射和Lambda表达式,提供了一种简洁高效的方式来操作对象的字段。它不仅提高了代码的可读性,还通过缓存机制优化了性能。掌握这个工具类的使用,将有助于提升Java开发的灵活性和效率。但使用反射仍然需要谨慎。反射操作可能会破坏封装性、增加性能开销,并可能引发安全问题。因此,在不需要动态访问的情况下,最好避免使用反射。
Hotool 不仅仅只有这一种工具类,还包含了其他许多工具类。在这里我作为一名Hutool的用户,我感谢Hutool的创作者和维护者们为我们带来如此强大便捷的工具库,希望Hutool功能越来越完善,为我们的开发工作带来更多的便利。同时也祝愿所有开发者没有BUG困扰,能够愉快地编写出高效、功能完善的程序。
相关文章:

【Hutool系列】反射工具-ReflectUtil
前言 反射是 Java 中一种强大的机制,可以在运行时动态地获取类的信息并操作类的属性和方法。在 Java 中,通过反射可以获取和设置类的字段、调用类的方法、创建类的实例等。Java的反射机制,可以让语言变得更加灵活,对对象的操作也更…...
【操作系统专业课】第二次作业
第1题(进程同步与互斥) 使用二值信号量实现 n 个进程之间的互斥。 1. 定义一个二值信号量 mutex= 1。 二值信号量:二值信号量只有两种取值,0 (资源已被占用)和 1(资源可用)。 2. 进程进入临界区前的操作:每个进程在进入临界区之前,都需要执行 P(mutex) 操作。 P 操作…...
Scala的迭代器
1.对比foreach 它的优点在于: (1) 内存效率高。迭代器采用延迟计算的方式,它不会将整个集合加载到内存中,而是在每次调用next方法时才计算并返回下一个元素。 (2) 统一的遍历方法。迭代器为不同类型的集合(如列表、集合、映射等…...

(RK3566驱动开发 - 1).pinctrl和gpio子系统
一.设备树 pinctrl部分可以参考 rockchip 官方的绑定文档 :kernel/Documentation/devicetree/bindings/pinctrl PIN_BANK:引脚所属的组 - 本次例程使用的是 GPIO3_A1 这个引脚,所以所属的组为 3; PIN_BANK_IDX:引脚的…...

css三角制作(二十课)
代码: <style>/* 边框原理 */.box1 {width: 0;height: 0;border-top: 100px solid pink;border-bottom: 100px solid blue;border-left: 100px solid yellow;border-right: 100px solid greenyellow;}/* 三角制作 */.box2 {width: 0;height: 0;border: 100px …...

C++_priority_queue(优先级队列)
✨✨ 欢迎大家来到小伞的大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C学习 小伞的主页:xiaosan_blog 1. priority_queue的介绍和使用 priority_queue文档介绍 优先级队列的实现的关键…...

微信小程序——01开发前的准备和开发工具
文章目录 一、开发前的准备1注册小程序账号2安装开发者工具 二、开发者工具的使用1创建项目2 工具的使用3目录结构4各个页面之间的关系5 权限管理6提交审核和发布 一、开发前的准备 开发前需要进行以下准备: 1 注册小程序账号2激活邮箱3 信息登记4 登录小程序管理后…...
MySQL 的主从复制数据同步
一、什么是 MySQL 的主从复制 MySQL 的主从复制(Master-Slave Replication)是一种将数据从一个主数据库服务器(主库)复制到一个或多个从数据库服务器(从库)的技术。主库负责所有的数据写操作,从…...

python——面向对象
一、面向对象编程 1.1 面向过程与面向对象 面向过程和面向对象都是一种编程方式,只不过再设计上有区别。 1.1.1 面向过程pop: 举例:孩子上学 1. 妈妈起床 2. 妈妈洗漱 3. 妈妈做饭 4. 妈妈把孩子叫起来 5. 孩子起床 6. 孩子洗漱 7. 孩子吃…...

Microsoft 365 Exchange如何设置可信发件IP白名单
1、 进入到 Microsoft 365 admin center 管理中心 ,点击 管理中心 下的 安全 在弹出的新页面中,依次点击 策略和规则 – 威胁策略 – 反垃圾邮件 再单击 连接筛选器策略(默认) – 编辑连接筛选器策略 2、在 IP 允许列表 中添加可信邮件 IP 段࿰…...

LM27313典型电路之升压电路
下图为升压芯片LM27313典型电路图: 从图中可以看出:系统电压VSYS3.7伏,通过C26与C27两个滤波电容后,到达升压芯片的VIN输入脚pin5。 其中电源芯片的电压输出由下式子决定: VOUT1.23*(1R17/R21) 其中VOUT是图中的V5D…...

嵌入式面试八股文(七)·#ifndef#define#endif的作用、以及内存分区(全局区、堆区、栈区、代码区)
目录 1. 头文件中的#ifndef / #define / #endif的作用是什么? 2. 内存分区:全局区、堆区、栈区、代码区简单描述? 2.1 代码区(Text Segment): 2.2 全局区(Data Segment)&…...

【弱监督视频异常检测】2024-ESWA-基于扩散的弱监督视频异常检测常态预训练
2024-ESWA-Diffusion-based normality pre-training for weakly supervised video anomaly detection 基于扩散的弱监督视频异常检测常态预训练摘要1. 引言2. 相关工作3. 方法论3.1. 使用扩散自动编码器进行常态学习3.2. 全局-局部特征编码器3.2.1 局部块3.2.2 全局块3.2.3 协同…...
Android 13 实现屏幕熄屏一段时候后关闭 Wi-Fi 和清空多任务列表
明白了,您这个补丁的功能是当设备屏幕关闭一段时间后,自动关闭 Wi-Fi 连接并清空多任务菜单。以下是更新后的博客内容,包含了对功能的详细解释和代码实现: 修改 PowerManagerService.java 以实现屏幕灭屏后关闭 Wi-Fi 和清空多任务菜单功能 在本篇博客中,我们将介绍一个针…...
Elasticsearch磁盘占用大于95%时将所有索引置为只读
在一个稳定运行的功能中,突然收到报错。经查明,是在向 Elasticsearch 中插入文档时出现了错误: AuthorizationException: AuthorizationException(403, ucluster_block_exception, ublocked by: [FORBIDDEN/12/index read-only / allow delete (api)];) 网上也有其他人报出类…...
删除 git config 保存的密码
要从 Git 中删除保存的密码,你可以根据你之前使用的保存方法来操作。以下是一些常见的方法来删除 Git 中保存的密码: 删除 credential.helper 中的密码 如果你之前使用 store 或 cache 作为 credential.helper,你可以执行以下步骤来删除保存…...
Springboot环境搭建详解
springboot学习视频记录: 笔记: a:Springboot maven常见依赖、配置文件笔记-CSDN博客 b:Springboot环境搭建详解-CSDN博客 day01 6:springboot的parent和starter依赖- a 7:启动类的位置配置- b 8&am…...

SpringCloud框架学习(第三部分:Resilience4j 与 Micrometer)
目录 九、CircuitBreaker断路器 1.前言(Hystrix) 2.服务雪崩 3.Circuit Breaker 4. Resilience4j 5.案例实战 (1)熔断(服务熔断 服务降级) Ⅰ. 按照 COUNT_BASED(计数的滑动窗口…...
Scala的Map集合(不可变)
package gxy//类型:不可变,可变 //操作:添加元素,删除元素,查询元素,移除元素,遍历 object map {def main(args: Array[String]): Unit {//不可变mapval map1 Map("鄂" -> "…...
深入剖析:Spring MVC与Struts的较量
标题:深入剖析:Spring MVC与Struts的较量 引言 在Java Web开发领域,Spring MVC和Struts是两个非常流行的框架。它们各自拥有不同的特点,适用于不同的应用场景。本文将深入探讨Spring MVC和Struts的区别,从底层机制、…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...

aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...