外观
深拷贝和浅拷贝的区别是什么
浅拷贝和深拷贝是在复制对象时的两种不同方式,它们的主要区别在于复制对象及其引用属性的程度。
浅拷贝定义
浅拷贝创建一个新对象,新对象的属性值会复制原始对象的属性值。对于基本数据类型,会直接复制其值;而对于引用数据类型,只会复制引用,即新对象和原始对象的引用属性会指向同一个内存地址,它们共享同一个对象实例。
示例代码
class Address {
String street;
String city;
public Address(String street, String city) {
this.street = street;
this.city = city;
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class ShallowCopyExample {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("123 Main St", "Anytown");
Person person1 = new Person("Alice", address);
// 进行浅拷贝
Person person2 = (Person) person1.clone();
// 修改 person2 的 address 的 street 属性
person2.address.street = "456 Elm St";
System.out.println(person1.address.street);
System.out.println(person2.address.street);
}
}
代码解释
在上述代码中,Person
类实现了 Cloneable
接口并重写了 clone()
方法。当调用 person1.clone()
进行浅拷贝时,person2
的 address
属性和 person1
的 address
属性指向同一个 Address
对象。所以当修改 person2.address.street
时,person1.address.street
也会被修改。
深拷贝定义
深拷贝同样会创建一个新对象,新对象的属性值会复制原始对象的属性值。与浅拷贝不同的是,对于引用数据类型,深拷贝会递归地复制其引用的对象,即新对象和原始对象的引用属性指向不同的内存地址,它们拥有各自独立的对象实例。
示例代码
class Address implements Cloneable {
String street;
String city;
public Address(String street, String city) {
this.street = street;
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person clonedPerson = (Person) super.clone();
// 深拷贝 address 属性
clonedPerson.address = (Address) address.clone();
return clonedPerson;
}
}
public class DeepCopyExample {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("123 Main St", "Anytown");
Person person1 = new Person("Alice", address);
// 进行深拷贝
Person person2 = (Person) person1.clone();
// 修改 person2 的 address 的 street 属性
person2.address.street = "456 Elm St";
System.out.println(person1.address.street);
System.out.println(person2.address.street);
}
}
代码解释
在上述代码中,Person
类和 Address
类都实现了 Cloneable
接口并重写了 clone()
方法。在 Person
类的 clone()
方法中,除了调用 super.clone()
复制基本数据类型和引用外,还对 address
属性进行了深拷贝,即调用 address.clone()
复制 Address
对象。这样,person2
的 address
属性和 person1
的 address
属性指向不同的 Address
对象,修改 person2.address.street
不会影响 person1.address.street
。
总结
- 浅拷贝只复制对象的一层属性,对于引用类型的属性只复制引用,多个对象共享同一个实例。
- 深拷贝会递归地复制对象及其所有引用类型的属性,每个对象都有自己独立的实例。在实际应用中,需要根据具体需求选择使用浅拷贝还是深拷贝。