如何优雅的合并两个对象

提出需求

相信很多时候,你可能有这样的需求,比如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;
    }
}
相关推荐
ccsd1140 分钟前
jmeter并发测试
java·jmeter
2401_857600953 小时前
电商系统开发:Spring Boot框架实战
java·spring boot·后端
WAXXD3 小时前
Java读取WPS excel.xlsx嵌入图片
java·excel·wps
yava_free3 小时前
详解一下JVM诊断方法和其工具的使用
java·开发语言
南宫生3 小时前
力扣-Hot100-二叉树其二【算法学习day.33】
java·数据结构·学习·算法·leetcode·动态规划
小吕学编程4 小时前
开发中SQL积累
java·数据库·sql
KevinAha4 小时前
Tomcat 8.5 源码导读
java·tomcat
她说人狗殊途4 小时前
设计模式学习
java·学习·设计模式
Mr.W.T4 小时前
JVM垃圾回收详解(重点)
java·jvm·算法
天草二十六_简村人4 小时前
spring-data-elasticsearch 3.2.4 实现桶bucket排序去重,实现指定字段的聚合搜索
java·spring boot·后端·spring·elasticsearch·架构·jenkins