You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效实现DTO类27个字段的空值与空字符串检查?

优化DTO字段空值检查的几种高效方案

1. 封装通用工具方法+Lambda表达式

针对非空判断+赋值的重复逻辑,封装一个通用工具方法,结合Lambda表达式简化代码,既保留直观性又减少重复:

import org.springframework.util.ObjectUtils;
import java.util.function.Consumer;

public class BuilderHelper {
    public static <T> void setIfNotEmpty(T value, Consumer<T> setter) {
        if (!ObjectUtils.isEmpty(value)) {
            setter.accept(value);
        }
    }
}

业务代码中调用方式:

BuilderHelper.setIfNotEmpty(updateRequest.getSettingType(), builder::setSettingType);
BuilderHelper.setIfNotEmpty(updateRequest.getSettingCode(), builder::setSettingCode);
BuilderHelper.setIfNotEmpty(updateRequest.getExecutionEndDate(), builder::setExecutionEndDate);
BuilderHelper.setIfNotEmpty(updateRequest.getStartToday(), builder::setStartToday);
// 剩余23个字段只需按此格式添加一行即可

优点:无额外依赖,代码简洁直观,运行时无性能损耗;缺点:仍需逐个字段声明,但相比原硬编码方式已大幅减少重复代码。

2. 利用Java反射批量处理

通过反射遍历DTO的字段,自动完成非空判断和赋值,无需为每个字段编写硬编码逻辑:

import org.springframework.util.ObjectUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public void populateBuilder(UpdateRequest updateRequest, EntityBuilder builder) {
    Field[] fields = UpdateRequest.class.getDeclaredFields();
    for (Field field : fields) {
        try {
            // 适配boolean类型的isXXX和普通类型的getXXX方法
            Method getter = getGetterMethod(field, UpdateRequest.class);
            Object value = getter.invoke(updateRequest);
            
            if (!ObjectUtils.isEmpty(value)) {
                Method setter = getSetterMethod(field, EntityBuilder.class);
                setter.invoke(builder, value);
            }
        } catch (Exception e) {
            // 处理字段无对应getter/setter等异常场景
            e.printStackTrace();
        }
    }
}

// 辅助方法:获取getter
private Method getGetterMethod(Field field, Class<?> clazz) throws NoSuchMethodException {
    String fieldName = field.getName();
    if (field.getType() == boolean.class || field.getType() == Boolean.class) {
        return clazz.getMethod("is" + capitalize(fieldName));
    } else {
        return clazz.getMethod("get" + capitalize(fieldName));
    }
}

// 辅助方法:获取setter
private Method getSetterMethod(Field field, Class<?> clazz) throws NoSuchMethodException {
    String setterName = "set" + capitalize(field.getName());
    return clazz.getMethod(setterName, field.getType());
}

// 辅助方法:首字母大写
private String capitalize(String name) {
    if (name == null || name.isEmpty()) return name;
    return name.substring(0, 1).toUpperCase() + name.substring(1);
}

优点:一次编码适配所有字段,新增字段无需修改逻辑;缺点:反射存在轻微性能损耗,对字段命名规范(get/is/set前缀)要求严格,需处理反射异常。

3. 使用MapStruct框架生成映射代码

MapStruct是编译期的Bean映射框架,支持通过注解配置非空忽略规则,自动生成高效的映射代码(无反射性能问题):

首先添加Maven依赖:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
    <scope>provided</scope>
</dependency>

定义映射接口:

import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValueCheckStrategy;
import org.mapstruct.NullValuePropertyMappingStrategy;

@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
        nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface UpdateRequestMapper {
    void updateBuilderFromRequest(UpdateRequest updateRequest, @MappingTarget EntityBuilder builder);
}

业务代码中调用:

// 注入映射接口实例(Spring环境下可直接@Autowired)
private UpdateRequestMapper mapper = UpdateRequestMapper.INSTANCE;

// 业务逻辑中调用
mapper.updateBuilderFromRequest(updateRequest, builder);

优点:编译期生成原生Java代码,性能优异,注解配置灵活,支持复杂映射场景;缺点:需要引入第三方框架,学习少量注解规则。


内容的提问来源于stack exchange,提问作者Doyel Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:27:23