BeanUtils拷贝属性容易忽视的坑

使用BeanUtils对两个对象进行属性拷贝(浅拷贝),方便快捷,减少了开发量,提高了开发效率,但是使用的时候要着重考虑下此处是否真的能用。
例如:

public class TestCopy {
    public static void main(String[] args) {
        Test test1 = new Test();
        Test test2 = new Test();
        test1.setA("a1");
//      test1.setB(1f);
        test2.setA("a2");
        test2.setB(2f);
        BeanUtils.copyProperties(test1, test2);
        System.out.println(test2.getA());
        System.out.println(test2.getB());
    }

}

class Test {
    private String a;
    private Float b;
    public String getA() {
        return a;
    }
    public void setA(String a) {
        this.a = a;
    }
    public Float getB() {
        return b;
    }
    public void setB(Float b) {
        this.b = b;
    }

}

用test1的属性覆盖test2的属性,但是当test1某属性为null时,我不希望test2的属性值丢失,相信这种场景大家也会经常遇到,比如前端修改一个对象,把修改后的对象传到后台,后台需要用这个对象更新持久层的实体,但是前端通常不可能将持久层实体涉及的所有属性都传到后台(因为有些属性是对前端屏蔽的,前端根本拿不到),这个时候如果使用BeanUtils直接拷贝,那么恭喜你,你的持久层数据被更新坏了

那么为什么会出现这个问题呢,我们以org.springframework.beans.BeanUtils为例,看下它的源码是如何实现的
这里写图片描述
第一个红框校验了源对象中是否有目标对象中需要更新的某属性,如果有就往下执行了
第二个红框从原对象中把该属性值取出,然后设置到目标对象中相应属性上

对比了其他几种BeanUtils源码(此处就不贴了),大体上都是这个思路,并不会检查原对象的属性是否为null,我想这可能是因为BeanUtils拷贝属性的设计初衷就是null也是一种属性值的状态,但是我们在使用的时候一定要根据自己的使用场景,谨慎使用!谨慎使用!谨慎使用!

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BeanUtils.copyProperties方法是Apache Commons BeanUtils库中的一个工具方法,用于将一个Java对象的属性拷贝到另一个Java对象中。它可以实现对象之间的属性值复制,无需手动逐个设置属性。 使用BeanUtils.copyProperties方法进行属性拷贝时,需要注意以下几点: 1. 属性名称和类型必须在源对象和目标对象中存在且匹配。 2. 属性值的拷贝是基于属性名称进行匹配的,而不是基于属性的位置。 3. 如果源对象和目标对象中存在相同名称但类型不匹配的属性,会抛出ConversionException异常。 4. 如果源对象中的属性值为null,则目标对象对应的属性值也会被设置为null。 5. 如果源对象和目标对象中存在嵌套对象,也会进行递归拷贝。 下面是一个示例代码,演示了如何使用BeanUtils.copyProperties方法进行属性拷贝: ```java import org.apache.commons.beanutils.BeanUtils; public class Main { public static void main(String[] args) { SourceObject source = new SourceObject(); source.setName("John"); source.setAge(25); TargetObject target = new TargetObject(); try { BeanUtils.copyProperties(target, source); System.out.println(target.getName()); // 输出:John System.out.println(target.getAge()); // 输出:25 } catch (Exception e) { e.printStackTrace(); } } } class SourceObject { private String name; private int age; // 省略getter和setter方法 } class TargetObject { private String name; private int age; // 省略getter和setter方法 } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值