Java实现对象复制合并 Java 对象合并 java对象复制 null值不复制, 目标对象有值 不覆盖
一、概述
近期的开发中,遇到一个需求, 有2个Java对象,需要合并成一个对象,然后去更新数据。 把2个对象合并为一个对象,规则是:
-
-
- 源对象: 属性为NULL ,则不覆盖 目标对象。
- 目标对象:属性不为NULL,则不需要覆盖。
-
实现思路: 初始的计划是,用反射的方式,获取2个对象的全部字段,然后逐个遍历,去逐一判断,若 源对象 字段为NULL,则忽略 ; 若 目标对象 属性不为NULL,则忽略。 伪代码,大致如下:
UserParam source = src;
UserParam target = dest;
for (Field s : source.getClass().getDeclaredFields()) {
s.setAccessible(true);
final Object o = s.get(source);
if(Objects.isNull(o)){
continue;
}
final Field t = target.getClass().getDeclaredField(s.getName());
t.setAccessible(true);
final Object o1 = t.get(target);
if(Objects.nonNull(o1)){
continue;
}
// 开始属性合并操作
t.set(target,o);
}
经过一番研究发现,hutool工具中,已经有对应的 BeanUtil 可以实现上述操作,且功能更强大,下面的案例中,将以 hutool BeanUtil 方式,实现Java 对象合并。
二、代码实现
1、有一个普通的Java Bean : UserParam
public class UserParam {
private Integer id ;
private String name ;
private String addr ;
private BigDecimal bigDecimal ; //测试传参空字符时的取值情况
// ignore getter , setter , toString()
}
2、hutool 依赖pom.xml
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.18</version>
</dependency>
3、测试代码如下
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
@Test
public void testFix() throws Exception{
final UserParam src = new UserParam();
src.setId(123);
src.setAddr("北京市");
src.setBigDecimal(BigDecimal.ZERO);
final UserParam dest = new UserParam();
dest.setName("二狗子");
dest.setBigDecimal(BigDecimal.TEN);
final CopyOptions copyOptions = CopyOptions.create();
copyOptions.setOverride(false);
copyOptions.setIgnoreNullValue(true);
BeanUtil.copyProperties(src,dest, copyOptions);
System.out.println(dest);
}
4、输出结果
src : UserParam [id=123, name=null, addr=北京市, bigDecimal=0]
dest : UserParam [id=123, name=二狗子, addr=北京市, bigDecimal=10]
三、总结
1、使用 hutool的BeanUtil 即可实现对象的合并,具体报名是: cn.hutool.core.bean.BeanUtil ,已经有对应的工具类实现,无需再重复编码。
2、可以关注hutool的CopyOptions , 有更多的对象合并选项可以配置,摘录如下:
protected Class<?> editable;
/**
* 是否忽略空值,当源对象的值为null时,true: 忽略而不注入此值,false: 注入null
*/
protected boolean ignoreNullValue;
/**
* 属性过滤器,断言通过的属性才会被复制
*/
protected BiPredicate<Field, Object> propertiesFilter;
/**
* 忽略的目标对象中属性列表,设置一个属性列表,不拷贝这些属性值
*/
protected String[] ignoreProperties;
/**
* 是否忽略字段注入错误
*/
protected boolean ignoreError;
/**
* 是否忽略字段大小写
*/
protected boolean ignoreCase;
/**
* 拷贝属性的字段映射,用于不同的属性之前拷贝做对应表用
*/
protected Map<String, String> fieldMapping;
/**
* 反向映射表,自动生成用于反向查找
*/
private Map<String, String> reversedFieldMapping;
/**
* 字段属性编辑器,用于自定义属性转换规则,例如驼峰转下划线等
*/
protected Editor<String> fieldNameEditor;
/**
* 字段属性值编辑器,用于自定义属性值转换规则,例如null转""等
*/
protected BiFunction<String, Object, Object> fieldValueEditor;
/**
* 是否支持transient关键字修饰和@Transient注解,如果支持,被修饰的字段或方法对应的字段将被忽略。
*/
protected boolean transientSupport = true;
/**
* 是否覆盖目标值,如果不覆盖,会先读取目标对象的值,非{@code null}则写,否则忽略。如果覆盖,则不判断直接写
*/
protected boolean override = true;
看了那么多,不如去亲自动手试一试咯~
参考资料: