一、什么是深拷贝?什么是浅拷贝?
Java中深拷贝和浅拷贝都是与Java中对象的复制有关。Java 中的深拷贝和浅拷贝通常通过实现 Cloneable 接口并重写 clone() 方法来实现。
浅拷贝:
在浅拷贝中,只有对象的基本数据类型属性被复制,而对象的引用类型属性则只是被复制了引用。这意味着新对象和原对象共享引用类型对象。
深拷贝:
在深拷贝中,会递归地复制对象及其所有子对象(无论是基本数据类型还是引用对象),确保新对象与原始对象完全独立。
二、浅拷贝示例
java
@Data
public class Teacher implements Cloneable{
private String name;
private int age;
private School school;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Teacher(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
}
@Data
@Accessors(chain = true)
public class Teacher implements Cloneable{
private String name;
private int age;
private School school;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); //浅拷贝
}
public Teacher(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
}
@Slf4j
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
School school = new School("AAA School");
Teacher teacher = new Teacher("Alice", 20, school);
Teacher backTeacher = (Teacher) teacher.clone();
backTeacher.setName("Tom");
backTeacher.setAge(18);
backTeacher.getSchool().setName("BBB School");
//将对象序列化为json字符串进行日志打印
String jsonTeacher = JSON.toJSONString(teacher);
String jsonBackTeacher = backTeacher.toString();
log.info("[Teacher] jsonTeacher name is : {}", jsonTeacher);
log.info("[Teacher] jsonBackTeacher name is : {}", jsonBackTeacher);
}
}
输出结果:
java
15:46:02.300 [main] INFO com.example.demo.entity.Main - [Teacher] teacher name is : {"age":20,"name":"Alice","school":{"name":"BBB School"}}
15:46:02.303 [main] INFO com.example.demo.entity.Main - [Teacher] teacher name is : Teacher(name=Tom, age=18, school=School(name=BBB School))
可以看到浅拷贝后,基本的数据类型修改没有影响,而对于引用对象数据修改后,原对象和复制的对象会联动修改
三、深拷贝示例
java
@Data
@Accessors(chain = true)
public class Teacher implements Cloneable{
private String name;
private int age;
private School school;
@Override
protected Object clone() throws CloneNotSupportedException {
Teacher cloneTeacher = (Teacher) super.clone();
cloneTeacher.school = (School) school.clone(); //深拷贝School对象
return cloneTeacher;
}
public Teacher(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
}
@Data
@Accessors(chain = true)
public class School implements Cloneable{
private String name;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public School(String name) {
this.name = name;
}
}
@Slf4j
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
School school = new School("AAA School");
Teacher teacher = new Teacher("Alice", 20, school);
Teacher backTeacher = (Teacher) teacher.clone();
backTeacher.setName("Tom");
backTeacher.setAge(18);
backTeacher.getSchool().setName("BBB School");
//将对象序列化为json字符串进行日志打印
String jsonTeacher = JSON.toJSONString(teacher);
String jsonBackTeacher = backTeacher.toString();
log.info("[Teacher] jsonTeacher name is : {}", jsonTeacher);
log.info("[Teacher] jsonBackTeacher name is : {}", jsonBackTeacher);
}
}
输出结果:
java
16:49:45.213 [main] INFO com.example.demo.entity.Main - [Teacher] jsonTeacher name is : {"age":20,"name":"Alice","school":{"name":"AAA School"}}
16:49:45.215 [main] INFO com.example.demo.entity.Main - [Teacher] jsonBackTeacher name is : Teacher(name=Tom, age=18, school=School(name=BBB School))
可以看到深拷贝后,原对象和拷贝后的对象无论是基本数据还是引用对象的数据都相互独立,互不影响。
四、项目中如何实现深拷贝
在项目中会借助fastjson库通过序列化+反序列化的方式实现对于复制对象的深拷贝
代码示例如下:
java
@Slf4j
public class Main {
/**
* 借助fastjson库 通过序列化 + 反序列化的方式实现对象的深拷贝
*
* @param object
* @param <T>
* @return
*/
public static <T> T deepCopy(T object) {
String jsonString = JSON.toJSONString(object);
return JSON.parseObject(jsonString, (Class<? extends T>) object.getClass());
}
public static void main(String[] args) throws CloneNotSupportedException {
School school = new School("AAA School");
Teacher teacher = new Teacher("Alice", 20, school);
//Teacher backTeacher = (Teacher) teacher.clone();
Teacher backTeacher = deepCopy(teacher);
backTeacher.setName("Tom");
backTeacher.setAge(18);
backTeacher.getSchool().setName("BBB School");
//将对象序列化为json字符串进行日志打印
String jsonTeacher = JSON.toJSONString(teacher);
String jsonBackTeacher = backTeacher.toString();
log.info("[Teacher] jsonTeacher name is : {}", jsonTeacher);
log.info("[Teacher] jsonBackTeacher name is : {}", jsonBackTeacher);
}
}
输出结果:
java
17:27:21.649 [main] INFO com.example.demo.entity.Main - [Teacher] jsonTeacher name is : {"age":20,"name":"Alice","school":{"name":"AAA School"}}
17:27:21.653 [main] INFO com.example.demo.entity.Main - [Teacher] jsonBackTeacher name is : Teacher(name=Tom, age=18, school=School(name=BBB School))