
本文介绍一种基于 java 8 函数式编程的简洁、可复用方式,通过泛型 + consumer 实现对 dto 字段的统一非空校验与赋值,避免为 27 个字段重复编写冗余 if 判断逻辑。
本文介绍一种基于 java 8 函数式编程的简洁、可复用方式,通过泛型 + consumer 实现对 dto 字段的统一非空校验与赋值,避免为 27 个字段重复编写冗余 if 判断逻辑。
在构建 DTO(Data Transfer Object)或使用 Builder 模式填充对象时,常需对多个 String 类型字段执行 null 和空字符串("")校验,确保仅当值有效时才调用对应 setter。若为每个字段单独写 if (!ObjectUtils.isEmpty(...)),不仅代码冗长、易出错,且难以维护——尤其当字段数达 27 个时,重复性极高。
一个高效、可扩展的解决方案是封装通用校验逻辑,利用 Java 8 的 Consumer
import org.springframework.util.ObjectUtils;
import java.util.function.Consumer;
private <t> void setFieldIfNotEmpty(Consumer<t> setter, T value) {
if (ObjectUtils.isNotEmpty(value)) {
setter.accept(value);
}
}</t></t>
该方法适用于任意类型(String、Number、Collection 等),内部委托 Spring 的 ObjectUtils.isNotEmpty() 进行健壮判断(支持 null、空字符串、空集合、空数组等常见“空”场景)。
使用时只需传入对应 setter 的方法引用和待赋值字段:
setFieldIfNotEmpty(builder::setSettingType, updateRequest.getSettingType()); setFieldIfNotEmpty(builder::setSettingCode, updateRequest.getSettingCode()); setFieldIfNotEmpty(builder::setExecutionEndDate, updateRequest.getExecutionEndDate()); // 注意:boolean 类型不适用此校验(null 不可能,且空语义不成立) builder.setStartToday(updateRequest.isStartToday()); // 直接赋值即可
✅ 优势总结:
- 零重复逻辑:27 个字段仅需 27 行简洁调用,无 if 块嵌套;
- 类型安全:泛型约束保证 setter 与 value 类型匹配;
- 可读性强:意图清晰——“若非空,则设值”;
- 易于扩展:如需支持默认值 fallback,可增强为 setFieldIfNotEmptyOrElse(..., defaultValue);
- 兼容主流工具类:ObjectUtils.isNotEmpty() 比 StringUtils.isNotBlank() 更全面(涵盖非 String 类型)。
⚠️ 注意事项:
- ObjectUtils.isNotEmpty() 对 Boolean、基本类型包装类(如 Integer)同样有效,但对原始 boolean/int 等无法判 null(本身不可为空),应直接赋值;
- 若项目未引入 Spring Framework,可用 Apache Commons Lang 的 StringUtils.isNotEmpty()(String 专用)或自行实现轻量判空工具;
- 避免在 setter 内部做空校验(违反单一职责),推荐将校验逻辑前置至构建/转换层。
通过这一模式,你不仅能显著减少样板代码,还能提升业务逻辑的清晰度与可测试性——让校验成为可组合、可复用的基础设施能力。











