如何优雅的合并两个对象

提出需求

相信很多时候,你可能有这样的需求,比如A对象的属性1、属性2是你需要的,其余属性是空值,而B对象的属性3、属性4是你需要的,其余属性是空值,那么如何将A对象的属性与B对象的属性结合呢?

思路解析

要实现将两个对象的属性结合,需要用到反射技术,遍历每个对象的属性,将非null的属性复制给null的属性,最后实现合并属性的效果。

常用的复制对象属性的方法(传统方案)

使用Java Bean Utils,这是Apache Commons BeanUtils库中的一个工具类,使用此工具类,则需要自己去实现判断属性的业务逻辑。

这个工具类有两个复制属性的方法,copyProperties和copyProperty。

static void copyProperties(Object dest, Object orig)Copy property values from the origin bean to the destination bean for all cases where the property names are the same.
static void copyProperty(Object bean, String name, Object value)Copy the specified property value to the specified destination bean, performing any type conversion that is required.

copyProperties方法会将orig(第二个对象)的属性复制给dest(第二个对象),这种复制是完全复制,会完全覆盖dest的属性。

copyProperty方法将复制value给bean的特定属性。

hutool合并对象的方案

Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类。

hutool常常被广大spring程序员唾弃,抱怨其在项目中的稳定性,bug问题。但我认为,hutool是一个在不断迭代和维护的库,虽然是国内程序员开发的,但是其中很多功能仍然是简单好用的,不能够以偏概全的全面否定它。

回归正题,下面做详细的说明

pom导入合并对象所必须的hutool库

xml 复制代码
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-core</artifactId>
    <version>5.8.16</version>
</dependency>

方法解释

  • cn.hutool.core.bean.BeanUtil
static <T> T copyProperties(Object source, Class<T> tClass, String... ignoreProperties)按照Bean对象属性创建对应的Class对象,并忽略某些属性
static void copyProperties(Object source, Object target, boolean ignoreCase)复制Bean对象属性
static void copyProperties(Object source, Object target, CopyOptions copyOptions)复制Bean对象属性 限制类用于限制拷贝的属性,例如一个类我只想复制其父类的一些属性,就可以将editable设置为父类
static void copyProperties(Object source, Object target, String... ignoreProperties)复制Bean对象属性 限制类用于限制拷贝的属性,例如一个类我只想复制其父类的一些属性,就可以将editable设置为父类

hutool的复制对象方法copyProperties有4个重载类型,在apache common beanutils的基础上,增加了一些复制选项,这些选项是非常实用的,比如忽略大小写、忽略某些属性、某些特定的复制选项等。

copyProperties(Object source, Object target, CopyOptions copyOptions)

因为我实际用了copyProperties(Object source, Object target, CopyOptions copyOptions),重点讲解此方法的传入参数。

CopyOptions包括以下的一些属性或选项,可以根据你的项目需求来选择

限定符和类型 字段和说明
protected TypeConverter converter自定义类型转换器,默认使用全局万能转换器转换
protected Class<?> editable限制的类或接口,必须为目标对象的实现接口或父类,用于限制拷贝的属性,例如一个类我只想复制其父类的一些属性,就可以将editable设置为父类 如果目标对象是Map,源对象是Bean,则作用于源对象上
protected BiFunction<String,Object,Object> fieldValueEditor字段属性值编辑器,用于自定义属性值转换规则,例如null转""等
protected boolean ignoreCase是否忽略字段大小写
protected boolean ignoreError是否忽略字段注入错误
protected boolean ignoreNullValue是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null
protected boolean override是否覆盖目标值,如果不覆盖,会先读取目标对象的值,非null则写,否则忽略。
protected boolean transientSupport是否支持transient关键字修饰和@Transient注解,如果支持,被修饰的字段或方法对应的字段将被忽略。

自己写的合并工具类

该工具类仅供参考,可以根据自己情况调整

java 复制代码
public class MergeUtil {
    private static final CopyOptions options = CopyOptions.create().setIgnoreNullValue(true).setOverride(false);
    private static final CopyOptions optionsAllowOverride = CopyOptions.create().setIgnoreNullValue(true).setOverride(true);

    //将tagetBean中的属性合并到sourceBean,忽略Null值,非Null值不允许覆盖
    public static Object merge(Object sourceBean, Object targetBean) {
        BeanUtil.copyProperties(sourceBean, targetBean, options);

        return targetBean;
    }

    //将tagetBean中的属性合并到sourceBean,忽略Null值,非Null值允许覆盖
    public static Object mergeAllowOverride(Object sourceBean, Object targetBean) {
        BeanUtil.copyProperties(sourceBean, targetBean, optionsAllowOverride);

        return targetBean;
    }
}
相关推荐
三七互娱后端团队2 分钟前
Serena语义检索在AI CodeReview中的应用
后端
Java水解2 分钟前
Nginx平滑升级与location配置案例详解
后端·nginx
好家伙VCC6 分钟前
**发散创新:探索群体智能编程中的新境界**随着科技的飞速发展,群体智能逐渐成为编程领域的一大研究热点。本文将深入探讨群体智能的概念、优
java·python·科技
秉承初心20 分钟前
Java 23种设计模式的详细解析
java·设计模式
千码君201625 分钟前
Go语言:记录一下Go语言系统学习的第一天
java·开发语言·学习·golang·gin·并发编程·编译语言
聪明的笨猪猪27 分钟前
Java 面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
渣哥33 分钟前
从 READ_UNCOMMITTED 到 SERIALIZABLE:Spring 事务隔离级别全解析
javascript·后端·面试
MrSYJ1 小时前
学完涨工资的技巧2:Spring Authorization Server如何签发JWTToken
java·spring boot·微服务
珹洺1 小时前
Java-Spring入门指南(二十六)Android Studio下载与安装
java·spring·android studio
JAVA学习通1 小时前
JDK高版本特性总结与ZGC实践
java·jvm·算法