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

【Hutool系列】反射工具-ReflectUtil

image

前言

  反射是 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困扰,能够愉快地编写出高效、功能完善的程序。

image

相关文章:

【Hutool系列】反射工具-ReflectUtil

前言 反射是 Java 中一种强大的机制&#xff0c;可以在运行时动态地获取类的信息并操作类的属性和方法。在 Java 中&#xff0c;通过反射可以获取和设置类的字段、调用类的方法、创建类的实例等。Java的反射机制&#xff0c;可以让语言变得更加灵活&#xff0c;对对象的操作也更…...

【操作系统专业课】第二次作业

第1题(进程同步与互斥) 使用二值信号量实现 n 个进程之间的互斥。 1. 定义一个二值信号量 mutex= 1。 二值信号量:二值信号量只有两种取值,0 (资源已被占用)和 1(资源可用)。 2. 进程进入临界区前的操作:每个进程在进入临界区之前,都需要执行 P(mutex) 操作。 P 操作…...

Scala的迭代器

1.对比foreach 它的优点在于&#xff1a; (1) 内存效率高。迭代器采用延迟计算的方式&#xff0c;它不会将整个集合加载到内存中&#xff0c;而是在每次调用next方法时才计算并返回下一个元素。 (2) 统一的遍历方法。迭代器为不同类型的集合&#xff08;如列表、集合、映射等…...

(RK3566驱动开发 - 1).pinctrl和gpio子系统

一.设备树 pinctrl部分可以参考 rockchip 官方的绑定文档 &#xff1a;kernel/Documentation/devicetree/bindings/pinctrl PIN_BANK&#xff1a;引脚所属的组 - 本次例程使用的是 GPIO3_A1 这个引脚&#xff0c;所以所属的组为 3&#xff1b; PIN_BANK_IDX&#xff1a;引脚的…...

css三角制作(二十课)

代码&#xff1a; <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(优先级队列)

✨✨ 欢迎大家来到小伞的大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 小伞的主页&#xff1a;xiaosan_blog 1. priority_queue的介绍和使用 priority_queue文档介绍 优先级队列的实现的关键…...

微信小程序——01开发前的准备和开发工具

文章目录 一、开发前的准备1注册小程序账号2安装开发者工具 二、开发者工具的使用1创建项目2 工具的使用3目录结构4各个页面之间的关系5 权限管理6提交审核和发布 一、开发前的准备 开发前需要进行以下准备&#xff1a; 1 注册小程序账号2激活邮箱3 信息登记4 登录小程序管理后…...

MySQL 的主从复制数据同步

一、什么是 MySQL 的主从复制 MySQL 的主从复制&#xff08;Master-Slave Replication&#xff09;是一种将数据从一个主数据库服务器&#xff08;主库&#xff09;复制到一个或多个从数据库服务器&#xff08;从库&#xff09;的技术。主库负责所有的数据写操作&#xff0c;从…...

python——面向对象

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

Microsoft 365 Exchange如何设置可信发件IP白名单

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

LM27313典型电路之升压电路

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

嵌入式面试八股文(七)·#ifndef#define#endif的作用、以及内存分区(全局区、堆区、栈区、代码区)

目录 1. 头文件中的#ifndef / #define / #endif的作用是什么&#xff1f; 2. 内存分区&#xff1a;全局区、堆区、栈区、代码区简单描述&#xff1f; 2.1 代码区&#xff08;Text Segment&#xff09;&#xff1a; 2.2 全局区&#xff08;Data Segment&#xff09;&…...

【弱监督视频异常检测】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 中删除保存的密码&#xff0c;你可以根据你之前使用的保存方法来操作。以下是一些常见的方法来删除 Git 中保存的密码&#xff1a; 删除 credential.helper 中的密码 如果你之前使用 store 或 cache 作为 credential.helper&#xff0c;你可以执行以下步骤来删除保存…...

Springboot环境搭建详解

springboot学习视频记录&#xff1a; 笔记&#xff1a; a&#xff1a;Springboot maven常见依赖、配置文件笔记-CSDN博客 b&#xff1a;Springboot环境搭建详解-CSDN博客 day01 6&#xff1a;springboot的parent和starter依赖- a 7&#xff1a;启动类的位置配置- b 8&am…...

SpringCloud框架学习(第三部分:Resilience4j 与 Micrometer)

目录 九、CircuitBreaker断路器 1.前言&#xff08;Hystrix&#xff09; 2.服务雪崩 3.Circuit Breaker 4. Resilience4j 5.案例实战 &#xff08;1&#xff09;熔断&#xff08;服务熔断 服务降级&#xff09; Ⅰ. 按照 COUNT_BASED&#xff08;计数的滑动窗口&#xf…...

Scala的Map集合(不可变)

package gxy//类型&#xff1a;不可变&#xff0c;可变 //操作&#xff1a;添加元素&#xff0c;删除元素&#xff0c;查询元素&#xff0c;移除元素&#xff0c;遍历 object map {def main(args: Array[String]): Unit {//不可变mapval map1 Map("鄂" -> "…...

深入剖析:Spring MVC与Struts的较量

标题&#xff1a;深入剖析&#xff1a;Spring MVC与Struts的较量 引言 在Java Web开发领域&#xff0c;Spring MVC和Struts是两个非常流行的框架。它们各自拥有不同的特点&#xff0c;适用于不同的应用场景。本文将深入探讨Spring MVC和Struts的区别&#xff0c;从底层机制、…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...