如何优雅的合并两个对象

提出需求

相信很多时候,你可能有这样的需求,比如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;
    }
}
相关推荐
予枫的编程笔记3 分钟前
【JDK版本】JDK版本迁移避坑指南:从8→17/21实操全解析
java·人工智能·jdk
独断万古他化3 分钟前
【MyBatis 深度解析】注解操作与 XML 配置:增删改查全流程实现
xml·java·spring·mybatis
西部风情3 分钟前
稳定性质量系列-系统稳定性建设实践
java·开发语言
短剑重铸之日4 分钟前
《7天学会Redis》Day 7 - Redisson 全览
java·数据库·redis·后端·缓存·redission
Qiuner5 分钟前
一文读懂 Lambda
java·spring boot·后端·架构
码界奇点6 分钟前
基于Spring+SpringMVC+MyBatis+easyUI的后台管理系统设计与实现
java·spring·毕业设计·mybatis·easyui·源代码管理
0和1的舞者7 分钟前
《#{} vs ${}:MyBatis 里这俩符号,藏着性能与安全的 “生死局”》
java·数据库·学习·mybatis·intellij idea·mybatis操作
程序新视界10 分钟前
“提供溢出的情绪价值”是AI产品极具可能性的方向
人工智能·后端·产品
步步为营DotNet11 分钟前
深度探究.NET中WeakReference:灵活内存管理的利器
java·jvm·.net
a程序小傲11 分钟前
中国邮政Java面试被问:Kafka的Log Compaction实现和删除策略
java·开发语言·后端·python·面试·职场和发展·kafka