目录
在 Java 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是两种对象复制的方式。它们在复制对象时的行为和效果有所不同,主要体现在对对象内部引用类型字段的处理上。下面详细介绍它们之间的区别:
1. 浅拷贝(Shallow Copy)
定义:
- 浅拷贝 是对对象进行复制的一种方式,它创建了一个新对象,该新对象的字段与原对象的字段指向相同的内存地址。换句话说,新对象和原对象共享对引用类型字段的引用。
特征:
- 对于基本类型字段,浅拷贝会创建基本数据类型的副本。
- 对于引用类型字段,浅拷贝只会复制引用,而不是引用所指向的对象。这意味着,原对象和新对象的引用类型字段指向同一内存位置。
实现:
- 可以通过
Object
类的clone()
方法实现浅拷贝,前提是类实现了Cloneable
接口。 - 默认的
clone()
方法实现的是浅拷贝。
示例:
class Person implements Cloneable {
String name;
int age;
Address address;
Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Address {
String city;
Address(String city) {
this.city = city;
}
}
public class ShallowCopyExample {
public static void main(String[] args) {
Address address = new Address("New York");
Person person1 = new Person("John", 30, address);
try {
// 进行浅拷贝
Person person2 = (Person) person1.clone();
// 修改浅拷贝后的对象的地址
person2.address.city = "Los Angeles";
// 输出原对象和拷贝对象的地址
System.out.println("Original person's address: " + person1.address.city);
System.out.println("Cloned person's address: " + person2.address.city);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
输出:
Original person's address: Los Angeles
Cloned person's address: Los Angeles
在上述示例中,person1
和 person2
的 address
字段指向同一个 Address
对象,因此更改 person2
的地址也影响了 person1
。
2. 深拷贝(Deep Copy)
定义:
- 深拷贝 是对对象进行复制的一种方式,它创建了一个新对象,并且递归地复制了原对象所引用的所有对象。换句话说,新对象和原对象不仅仅是新对象的字段被复制,而且引用的对象也会被复制,确保新对象与原对象完全独立。
特征:
- 对于基本类型字段,深拷贝会创建基本数据类型的副本。
- 对于引用类型字段,深拷贝会复制引用的对象,确保新对象中的引用指向新创建的对象,而不是原对象中引用的对象。
实现:
- 深拷贝需要手动实现,通常在
clone()
方法中递归地拷贝引用类型字段,或使用序列化和反序列化来实现深拷贝。
示例:
class Person implements Cloneable {
String name;
int age;
Address address;
Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
// 深拷贝 address 对象
cloned.address = new Address(this.address.city);
return cloned;
}
}
class Address {
String city;
Address(String city) {
this.city = city;
}
}
public class DeepCopyExample {
public static void main(String[] args) {
Address address = new Address("New York");
Person person1 = new Person("John", 30, address);
try {
// 进行深拷贝
Person person2 = (Person) person1.clone();
// 修改深拷贝后的对象的地址
person2.address.city = "Los Angeles";
// 输出原对象和拷贝对象的地址
System.out.println("Original person's address: " + person1.address.city);
System.out.println("Cloned person's address: " + person2.address.city);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
输出:
Original person's address: New York
Cloned person's address: Los Angeles
在深拷贝的示例中,person1
和 person2
的 address
字段指向不同的 Address
对象,因此更改 person2
的地址不会影响 person1
。
总结
- 浅拷贝:复制对象时,只复制对象的引用类型字段的引用,而不是实际的引用对象。这可能导致原对象和新对象共享同一引用对象。
- 深拷贝:复制对象时,不仅复制对象本身,还递归地复制对象所引用的所有对象,确保新对象与原对象完全独立。