public static <T> String convert(String idString,
Function<List<String>, List<T>> queryFunction,
Function<T, String> idGetter,
Function<T, String> nameGetter){
//具体实现
}工具类原文链接:我用夸克网盘给你分享了「逗号分隔ID转名称」,链接:https://pan.quark.cn/s/5996dcb37237
这个convert方法是一个典型的通用工具方法,核心是通过「泛型」和「函数式接口」实现对不同场景的适配。我们可以从「泛型设计」「参数作用」「逻辑流程」三个角度拆解,理解它为什么能通用,以及如何写出类似的工具类。
一、先看懂:泛型 <T> 是啥?
方法定义中的 <T> 是「泛型参数」,你可以把它理解为一个“占位符”,代表任意实体类类型(比如Subject、User、Dept等)。
- 为什么需要它?
工具类的目的是“通用”,如果不写泛型,方法就只能固定处理某一种实体(比如只能处理Subject),无法复用。有了<T>,这个方法可以同时处理User、Dept等任何实体,只要它们有“ID”和“名称”字段。 - 举例:
当处理学科时,T就是Subject;处理用户时,T就是User。方法会根据实际传入的类型自动适配,不需要重复写多个类似的方法。
二、再拆参数:3个Function到底在干嘛?
方法的4个参数中,后3个Function是核心,它们负责把“可变的逻辑”从工具类中抽离出来(让工具类只保留通用逻辑)。
我们用一个具体场景(把课程的“学科ID字符串”转“学科名称”)来对应参数,就很容易理解:
参数 | 类型 | 作用 | 例子(学科场景) |
|
| 原始输入:逗号分隔的ID字符串(比如"1,2,3") | 课程的 |
|
| 传入“根据ID列表查实体”的逻辑 |
|
|
| 传入“从实体中取ID”的逻辑 |
|
|
| 传入“从实体中取名称”的逻辑 |
|
public String getSubjectNames(TbCourse tbCourse) {
String subjectInfo = tbCourse.getSubjectInfo(); // 逗号分隔的学科 ID 字符串
return IdToNameConverter.convert(
subjectInfo,
// 1. 查询函数:根据 ID 列表查学科
ids -> tbCourseMapper.selectByIds(ids),
// 2. 从学科实体取 ID
TbCourse::getId,
// 3. 从学科实体取名称
TbCourse::getName
);
}关键:Function是“输入→输出”的转换器
Function<A, B> 是Java的函数式接口,代表“接收A类型参数,返回B类型结果”的转换规则。
比如 idGetter 是 Function<T, String>,意思是“接收一个T类型的实体(比如Subject),返回一个String类型的ID”。
三、逻辑流程:通用工具类的“不变”与“变”
这个方法的核心逻辑是固定的流程,但流程中的“具体操作”通过参数传入(即“变”的部分)。整体步骤如下:
原始ID字符串 → 拆分ID列表 → 查实体列表(用queryFunction) → 建ID→名称映射(用idGetter和nameGetter) → 拼接名称字符串分步拆解(结合学科场景):
- 处理空输入:如果
idString是null或空,直接返回空字符串(避免空指针)。
(通用逻辑:所有场景都需要处理空值) - 拆分ID列表:把"1,2,3"拆成
["1", "2", "3"](去空格、过滤空值)。
(通用逻辑:所有“逗号分隔ID”场景都需要拆分) - 查询实体列表:调用
queryFunction,传入拆分后的ID列表,得到实体列表(比如List<Subject>)。
(可变逻辑:查学科用subjectMapper,查用户用userMapper,由参数传入) - 构建ID→名称映射:遍历实体列表,用
idGetter取ID、nameGetter取名称,存到Map中(比如{"1":"数学", "2":"语文"})。
(可变逻辑:不同实体的ID和名称字段不同,由参数传入) - 拼接名称字符串:按原始ID顺序,从
Map中取名称拼接(比如"数学, 语文")。
(通用逻辑:所有场景都需要按原顺序拼接)
四、为什么这样写能成为“通用工具类”?
通用工具类的核心设计思路是:把“不变的通用逻辑”写死在工具类里,把“变化的具体逻辑”通过参数传进来。
- 不变的逻辑:拆分ID、处理空值、拼接名称(这些是所有“ID转名称”场景共有的)。
- 变化的逻辑:查哪个表、ID字段叫什么、名称字段叫什么(这些因场景而异,通过参数传入)。
这种设计让一个方法能顶多个用,比如同样的convert方法,既能处理“学科ID转名称”,也能处理“用户ID转用户名”“部门ID转部门名”,不需要重复写代码。
五、自己写通用工具类的3个关键步骤
- 识别“通用逻辑”和“可变逻辑”:
比如“ID转名称”中,拆分、拼接是通用的;查询、取字段是可变的。 - 用泛型
<T>适配不同类型:
如果你需要处理多种实体(User、Dept等),用泛型代替具体类型,让工具类“不绑定”某一种实体。 - 用函数式接口传递可变逻辑:
用Function(转换)、Predicate(判断)等接口,把可变的操作通过参数传入(就像把“具体做什么”告诉工具类)。
总结
这个convert方法之所以通用,是因为它没有硬编码任何具体业务(比如只查学科表),而是通过泛型适配不同实体,通过Function参数接收具体操作。理解了“泛型占位”和“函数传参”这两个点,就能慢慢写出灵活的通用工具类了。
















