IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 关于Spring中BeanUtils.copyProperties的注意事项 -> 正文阅读

[Java知识库]关于Spring中BeanUtils.copyProperties的注意事项

在写需求时遇到了个bug,关于这个方法的用法产生了点疑问,不知道算是深拷贝还是浅拷贝。自己写了个类

  1. src和target无子对象
@Data
public class T1 {
    private String name;
    private List<String> values;
}
@Data
public class T2 {
    private String name;
    private List<String> values;
}
List<String> s1 = new ArrayList<>();
        List<String> s2 = new ArrayList<>();
        s1.add("11");
        s1.add("22");
        s2.add("op");
        T1 t1 = new T1();
        t1.setValues(s1);
        t1.setName("t1");
        T2 t2 = new T2();
        BeanUtils.copyProperties(t1,t2);
        System.out.println(t2.getValues());
        t1.setValues(s2);
        System.out.println(t2.getValues());

如果是拷贝的引用,那么两次输出的应该不一样,但是结果是两次输出都一样。
在这里插入图片描述
在这里插入图片描述
这种情况和我遇到的bug不太一样,我就又试了如果是子对象的情况。

  1. src和target有子对象集合
@Data
public class T1 {
    private String name;
    private List<Son1> values;
}
@Data
public class T2 {
    private String name;
    private List<Son2> values;
}
@Data
public class Son1 {
    private String age;
    private String sex;
}
@Data
public class Son2 {
    private String age;
    private String sex;
}
List<Son1> s1 = new ArrayList<>();
        List<Son1> s2 = new ArrayList<>();
        Son1 son1 = new Son1();
        son1.setAge("18");
        son1.setSex("male");
        s1.add(son1);
        T1 t1 = new T1();
        t1.setValues(s1);
        t1.setName("t1");
        T2 t2 = new T2();
        BeanUtils.copyProperties(t1,t2);
        System.out.println(t2.getValues());
        t1.setValues(s2);
        System.out.println(t2.getValues());

此时,神奇的事情来了,如果赋值的两个类的属性名一样,但是种类不同,他还是会把source的种类复制到target上。看一下调试结果:
在这里插入图片描述
明明T2这个类的values属性应该是List<Son2>,但是现在却变成了List<Son1>!!!

再玩的花一点,把T2的属性改为其它类,T1的属性不变:

@Data
public class T2 {
    private String name;
    private List<OrderVO> values;
}
List<Son1> s1 = new ArrayList<>();
        List<Son1> s2 = new ArrayList<>();
        Son1 son1 = new Son1();
        son1.setAge("18");
        son1.setSex("male");
        s1.add(son1);
        T1 t1 = new T1();
        t1.setValues(s1);
        t1.setName("t1");
        T2 t2 = new T2();
        BeanUtils.copyProperties(t1,t2);
        System.out.println(t2.getValues());
        List<OrderVO> t2Values = t2.getValues();
        t1.setValues(s2);
        System.out.println(t2.getValues());
        System.out.println(t2Values.get(0).getFee());

更神奇的事情又来了,虽然T2的values属性是List<OrderVO>了。但是BeanUtils方法运行完毕赋值的还是List<Son1>
在这里插入图片描述
在这里插入图片描述

看这一行代码List<OrderVO> t2Values = t2.getValues();居然不报错能执行成功,但是当执行到真的从list中取对象的时候System.out.println(t2Values.get(0).getFee());就会报错,错误是java.lang.ClassCastException。。。害人不浅啊!
个人觉得是运行时类型不匹配不会报错,编译时检查你的写法没问题,所以代码可以运行,但是真的取数据时才会报错。

  1. src和target只有子对象
    如果values属性不是集合,而是单纯的子对象,那么就不会复制成功。
@Data
public class T1 {
    private String name;
    private Son1 values;
}
@Data
public class T2 {
    private String name;
    private OrderVO values;
}

运行结果如下:
在这里插入图片描述

Tips:
1.BeanUtils.copyProperties确实是深拷贝,list类型不是复制的引用,原有list改变不会影响复制后的;
2.如果拷贝的属性是子对象的集合,那么需要确保src和target的子对象是同一个类,否则就自己再写一遍BeanUtils.copyProperties来拷贝子对象。
3.如果拷贝的对象的属性只是个子对象,而且target和src的子对象不是同一个,那么即便属性名相同也不会复制,target中相关属性只会是null。

个人猜测为什么子对象集合不行,可能判断是否能复制是根据属性名和类型来的,对于List中的每个对象,可能jvm都当成了一个类似于json的东西,只判断了都是集合,没有去判断集合里的对象是不是同一个。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-18 23:18:09  更:2022-06-18 23:19:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 7:01:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码