如何优雅的合并两个对象

提出需求

相信很多时候,你可能有这样的需求,比如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;
    }
}
相关推荐
mango02191 分钟前
SpringMVC
java
Seven977 分钟前
SpringCloud带你走进微服务的世界
java·后端·spring cloud
Vacant Seat38 分钟前
图论-实现Trie(前缀树)
java·开发语言·数据结构·图论
工一木子1 小时前
【HeadFirst系列之HeadFirstJava】第16天之深入解析 Java 集合与泛型:高效管理数据的终极指南!(含代码实战)
java·集合·泛型
夕颜1111 小时前
排查问题的知识记录
后端
zhuyasen1 小时前
Go语言Viper配置详解:conf库优雅解析实战
后端·golang
佳佳_1 小时前
Spring Boot SSE 示例
spring boot·后端
Yuanymoon2 小时前
【由技及道】统一封装API返回结果后String返回报错文件解决原理--Spring 消息转换器的层次图解与规则说明【人工智障AI2077的开发问题日志002】
java·spring
听风说雨的人儿2 小时前
ES6 class的继承概念
java·前端·es6
l_tian_tian_2 小时前
JavaWeb——Mybatis、JDBC、数据库连接池、lombok
java·数据库·mybatis