简单介绍
我们在平时开发过程中或多或少会遍历一个java集合(暂且以List为例说明),然后根据遍历的每一个对象,处理不同的业务逻辑,本文要阐述的是我们平时处理业务逻辑时会获取数据库的数据结果对象或者用户编辑数据对象或者缓存中的数据对象等等凡是不等于集合中遍历结果的对象都可以,我们根据这些业务衍生的对象给集合遍历结果的对象赋值,往往会发现明明同一个类型(同一个类)只是不同的实例而已,赋值给集合中的对象后 再去查询集合的数据结果,发现集合中的对象还是以前的数据,是不是很奇怪,要知道具体什么原因请耐心看我的后续解释。
问题现象
为了直观一些,我们先来看下这段代码和运行的效果
List<LeanBO> leanBOList = new ArrayList<LeanBO>();
LeanBO leanBO = new LeanBO();
leanBO.setSno(202101L);
leanBO.setSname("你好202101");
leanBOList.add(leanBO);
System.out.println("原始集合数据"+JSON.toJSONString(leanBOList));
for (LeanBO leanTemp:leanBOList) {
//模拟从数据库查询出息的leanBO对象
LeanBO leanBODB = new LeanBO();
leanBODB.setSno(202102L);
leanBODB.setSname("你好202102");
leanTemp = leanBODB;
}
System.out.println("处理业务结束后的集合数据"+JSON.toJSONString(leanBOList));
运行的效果如下:
大家看到运行结果是不是觉得诧异 怎么回事?我不是把leanBODB赋值给集合遍历的结果对象leanTemp了吗?为什么集合的数据还是以前的?
解释原因
从以上代码可以看到是对象间的直接赋值,在数据结构上 其实就是leanBODB对象的引用地址指向了leanTemp,即两个对象公用一个内存地址,但是新修改的地址没有重新加入到链表中,因为链表中存储的还是老的对象的引用地址,所以最终输出的结果是赋值之前的数据
解决方法
1、可以把老的对象从集合中移除,然后再把新的业务对象加入到集合中,具体实现代码如下:
List<LeanBO> leanBOList = new ArrayList<LeanBO>();
LeanBO leanBO = new LeanBO();
leanBO.setSno(202101L);
leanBO.setSname("你好202101");
leanBOList.add(leanBO);
System.out.println("原始集合数据"+JSON.toJSONString(leanBOList));
for (LeanBO leanTemp:leanBOList) {
//模拟从数据库查询出来的leanBO对象
LeanBO leanBODB = new LeanBO();
leanBODB.setSno(202102L);
leanBODB.setSname("你好202102");
leanBOList.remove(leanTemp);//移除老的对象
leanBOList.add(leanBODB);//加入新的对象
}
System.out.println("处理业务结束后的集合数据"+JSON.toJSONString(leanBOList));
运行的结果如下:
原始集合数据[{"sname":"你好202101","sno":202101}]
处理业务结束后的集合数据[{"sname":"你好202102","sno":202102}]
2、可以不修改原始集合中对象的引用,而是重新修改对象的属性值,具体代码如下:
List<LeanBO> leanBOList = new ArrayList<LeanBO>();
LeanBO leanBO = new LeanBO();
leanBO.setSno(202101L);
leanBO.setSname("你好202101");
leanBOList.add(leanBO);
System.out.println("原始集合数据"+JSON.toJSONString(leanBOList));
for (LeanBO leanTemp:leanBOList) {
//模拟从数据库查询出来的leanBO对象
LeanBO leanBODB = new LeanBO();
leanBODB.setSno(202102L);
leanBODB.setSname("你好202102");
leanTemp.setSno(leanBODB.getSno());//重新赋值sno
leanTemp.setSname(leanBODB.getSname());//重新赋值sname
}
System.out.println("处理业务结束后的集合数据"+JSON.toJSONString(leanBOList));
运行结果如下:
原始集合数据[{"sname":"你好202101","sno":202101}]
处理业务结束后的集合数据[{"sname":"你好202102","sno":202102}]
3、可以采用第三方组件API:BeanUtils.copyproperties()深度拷贝对象