如何优雅的合并两个对象
提出需求
相信很多时候,你可能有这样的需求,比如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库
<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注解,如果支持,被修饰的字段或方法对应的字段将被忽略。 |
自己写的合并工具类
该工具类仅供参考,可以根据自己情况调整
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);
//将sourceBean中的属性合并到tagetBean,忽略Null值,非Null值不允许覆盖
public static Object merge(Object sourceBean, Object targetBean) {
BeanUtil.copyProperties(sourceBean, targetBean, options);
return targetBean;
}
//将sourceBean中的属性合并到tagetBean,忽略Null值,非Null值允许覆盖
public static Object mergeAllowOverride(Object sourceBean, Object targetBean) {
BeanUtil.copyProperties(sourceBean, targetBean, optionsAllowOverride);
return targetBean;
}
}
来源:juejin.cn/post/7290475242274258978