微信技术群:Day9884125
一 背景
我们经常将一个对象复制到另一个对象上,但是特殊情况下我们会将对象复制到同一个对象上。这时会出现共用一个内存地址的问题。
二 代码演示
2.1 问题代码
package com.day.controller;
import com.day.pojo.Dept;
import java.util.ArrayList;
import java.util.List;
public class UserCopyDemo {
public static void main(String[] args) {
UserCopyDemo demo = new UserCopyDemo();
List<Dept> list = demo.getList();
list.stream().forEach(dept -> System.out.println(dept));
}
public List<Dept> getList(){
List<Dept> list = new ArrayList<Dept>();
Dept dept = new Dept();
dept.setAddr("河北");
dept.setName("张三");
dept.setSex("男");
list = getDepts(dept);
return list;
}
public List<Dept> getDepts(Dept dept){
List<Dept> list = new ArrayList<Dept>();
for(int i = 0; i<3; i++){
Dept dept2 = new Dept();
dept2 = dept;
dept2.setName("李"+i);
list.add(dept2);
}
return list;
}
}
2.2 解决方式
解决新旧对象共用内存地址的问题,可以使用深拷贝的方式解决。
package com.day.controller;
import com.day.pojo.Dept;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
public class UserCopyDemo {
public static void main(String[] args) {
UserCopyDemo demo = new UserCopyDemo();
List<Dept> list = demo.getList();
list.stream().forEach(dept -> System.out.println(dept));
}
public List<Dept> getList(){
List<Dept> list = new ArrayList<Dept>();
Dept dept = new Dept();
dept.setAddr("河北");
dept.setName("张三");
dept.setSex("男");
list = getDepts(dept);
return list;
}
public List<Dept> getDepts(Dept dept){
List<Dept> list = new ArrayList<Dept>();
for(int i = 0; i<3; i++){
Dept dept2 = new Dept();
/**
* BeanUtils是spring提供的深拷贝工具类,
* apache提供的参数正好相反
* 而原生的对代码又侵入性太强
*/
BeanUtils.copyProperties(dept, dept2);
dept2.setName("李"+i);
list.add(dept2);
}
return list;
}
}
三 基础知识介绍
3.1 深拷贝和浅拷贝
在很多时候都会遇到拷贝的问题,我们总是需要将一个对象复制到另一个对象上。当新旧对象都是同一个对象的时候,我们改变新赋值对象的时候,我们再用旧的对象中的某个值,这时候发现旧的对象也变成了新对象的内容。这时候就用到了拷贝概念
浅拷贝:将原数据的内存地址引用到新的数据中,它们实际共享的是一个内存地址。目的是为了优化硬件空间。
public User getUser(User user){
// 这就是浅拷贝的例子,实际两个对象共用的一个内存地址
User user2 = new User();
user2 = user;
}
深拷贝:创建一个新的数据,将原数据的各项属性的值拷贝过去,而不是简单的将内存地址引用过去,而造成的数据相同,实际上是又开辟了一个内存地址。
注意: 深拷贝和浅拷贝针对的是引用数据类型。而基本数据类型不存在拷贝问题,它的赋值就是新开辟内存地址。