【Java基础面试题041】Java中的深拷贝和浅拷贝有什么区别?
回答重点
深拷贝:深拷贝不仅复制对象本身,还递归复制对象中所有引用的对象。这样新对象与原对象完全独立,修改新对象不会影响到原对象。即包括基本类型和引用类型,堆内的引用对象也会复制一份
浅拷贝:浅拷贝只复制对象的引用,而不复制引用指向的实际对象,也就是说,浅拷贝创建一个新对象,但它的字段(若是对象类型)指向的是原对象中的相同内存地址
深拷贝创建的新对象与原对象完全独立,任何一个对象的修改都不会影响另一个。二修改浅拷贝对象中的引用类型的字段会影响要原对象,因为它们共享相同的引用
扩展知识
图示深浅拷贝
浅拷贝实现
常见实现方式是重写Object.clone()方法,默认方法这个方法只是对对象的字段进行字段拷贝,对于基本类型的字段会复制值,对于引用类型的字段则复制引用
重写Clone()的类需要实现Cloneable接口,否则抛出异常CloneNotSupportedException
public class ShallowCopyTest {
public static void main(String[] args) throws CloneNotSupportedException{
ShallowCopyTest test = new ShallowCopyTest();
Person john = test.new Person("John", 25, new ArrayList<>(Arrays.asList("电玩", "旅游")));
Person johnCopy = (Person) john.clone();
System.out.println(john);
System.out.println(johnCopy);
System.out.println(john.hobbies == johnCopy.hobbies);
}
class Person implements Cloneable{
String name;
int age;
List<String> hobbies;
public Person(String name, int age, List<String> hobbies) {
this.name = name;
this.age = age;
this.hobbies = hobbies;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString(){
return name + "已经" + age + "岁了,喜欢" + hobbies.get(0) + " 和 " + hobbies.get(1);
}
}
}
深拷贝实现
深拷贝可以通过递归调用clone()方法手动实现,也可以通过序列化与反序列化实现。序列化方式简单易用,但性能相对较低,尤其是在深层嵌套对象或大对象的情况下。
- 递归调用clone()实现
public class DeepCopyTest {
public static void main(String[] args) throws CloneNotSupportedException {
DeepCopyTest test = new DeepCopyTest();
People people = test.new People("Autism", 21, test.new Address("HeFei"));
People clone = (People) people.clone();
System.out.println(people.address == clone.address);
}
class People implements Cloneable{
String name;
int age;
Address address;
public People(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
People p = (People) super.clone(); // 先浅拷贝
p.address = (Address) address.clone(); // 引用字段手动拷贝
return p;
}
}
class Address implements Cloneable{
String city;
public Address(String city){
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}
- 序列化实现
public static Object deepCopy(Object object) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}