目录
class Address implements Cloneable {
public String city;
public String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
在编程中,深拷贝和浅拷贝是用于复制对象的两种不同方式。它们之间的主要区别在于它们如何处理引用类型的成员。
一、浅拷贝 (Shallow Copy)
浅拷贝创建一个新对象,这个新对象的属性包含与原对象相同的值。对于值类型(如整数、浮点数、布尔值等),它会直接复制这些值。而对于引用类型(如对象、数组等),它会复制引用,因此新对象中的属性和原对象中的属性引用同一个内存地址。
换句话说,浅拷贝只复制对象的第一层。如果对象中的属性是引用类型,那么浅拷贝不会复制这些引用类型对象,而是复制它们的引用。
例如:
public class Person implements Cloneable{
public String name;
public int age;
public Address address;
public 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 {
public String city;
public String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("北京", "八里庄街道");
Person person1 = new Person("李明", 30, address);
Person person2 = (Person) person1.clone();
System.out.println(person1.address.city); // 北京
System.out.println(person2.address.city); // 北京
person2.address.city = "洛杉矶";
System.out.println(person1.address.city); // 洛杉矶
System.out.println(person2.address.city); // 洛杉矶
}
}
在上面的例子中,person1
和 person2
都引用同一个 Address
对象,因此修改 person2.address.city
会影响到 person1.address.city
。
二、深拷贝 (Deep Copy)
深拷贝不仅复制对象本身,还递归地复制对象中引用的所有对象。因此,新对象和原对象是完全独立的,修改新对象不会影响到原对象。
例如:
public class Person implements Cloneable {
public String name;
public int age;
public Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
protected Object clone(){
Person cloned = null;
try {
cloned = (Person) super.clone();
cloned.address = (Address) address.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
return cloned;
}
}
class Address implements Cloneable {
public String city;
public String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
注意看,深拷贝,Address类也实现了Clonable接口,重写了clone方法。
public class Main {
public static void main(String[] args) {
Address address = new Address("北京", "上海路");
Person person1 = new Person("徐佳莹", 30, address);
Person person2 = (Person) person1.clone();
System.out.println(person1.address.city); // 北京
System.out.println(person2.address.city); // 北京
person2.address.city = "莫斯科";
System.out.println(person1.address.city); // 北京
System.out.println(person2.address.city); // 莫斯科
}
}
在这个例子中,通过重写 clone
方法实现深拷贝,person1
和 person2
拥有独立的 Address
对象,因此修改 person2.address.city
不会影响 person1.address.city
。
三、总结
- 浅拷贝:只复制对象的第一层,引用类型成员仍然指向原来的对象。
- 深拷贝:递归地复制对象和它包含的所有对象,生成完全独立的副本。