在 Java 里,对象克隆指的是创建一个与已有对象内容相同的新对象。Java 提供了两种克隆方式:浅克隆和深克隆。下面会详细阐述这两种克隆方式。
浅克隆
浅克隆会创建一个新对象,新对象的属性和原对象相同。若属性是引用类型,新对象和原对象会共享同一个引用。Java 中可通过实现 Cloneable
接口并覆写 clone()
方法达成浅克隆。
以下是浅克隆的示例代码:
class Address {
String street;
String city;
public Address(String street, String city) {
this.street = street;
this.city = city;
}
}
class Person implements Cloneable {
String name;
int age;
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();
}
}
public class ShallowCloneExample {
public static void main(String[] args) {
Address address = new Address("123 Main St", "Anytown");
Person person1 = new Person("John", 30, address);
try {
Person person2 = (Person) person1.clone();
System.out.println("Original Person: " + person1.name + ", " + person1.age + ", " + person1.address.street + ", " + person1.address.city);
System.out.println("Cloned Person: " + person2.name + ", " + person2.age + ", " + person2.address.street + ", " + person2.address.city);
// 修改克隆对象的地址
person2.address.street = "456 Elm St";
System.out.println("After modification:");
System.out.println("Original Person: " + person1.name + ", " + person1.age + ", " + person1.address.street + ", " + person1.address.city);
System.out.println("Cloned Person: " + person2.name + ", " + person2.age + ", " + person2.address.street + ", " + person2.address.city);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
在上述示例中,Person
类实现了 Cloneable
接口并重写了 clone()
方法。clone()
方法调用了 super.clone()
来创建一个浅克隆对象。当修改克隆对象的 address
属性时,原对象的 address
属性也会被修改,这是因为它们共享同一个 Address
对象的引用。
深克隆
深克隆会创建一个新对象,并且会递归地克隆对象的所有引用类型属性。也就是说,新对象和原对象的所有属性都是独立的。可以通过手动复制引用类型属性来实现深克隆。
以下是深克隆的示例代码:
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;
int age;
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 {
Person cloned = (Person) super.clone();
cloned.address = (Address) address.clone();
return cloned;
}
}
public class DeepCloneExample {
public static void main(String[] args) {
Address address = new Address("123 Main St", "Anytown");
Person person1 = new Person("John", 30, address);
try {
Person person2 = (Person) person1.clone();
System.out.println("Original Person: " + person1.name + ", " + person1.age + ", " + person1.address.street + ", " + person1.address.city);
System.out.println("Cloned Person: " + person2.name + ", " + person2.age + ", " + person2.address.street + ", " + person2.address.city);
// 修改克隆对象的地址
person2.address.street = "456 Elm St";
System.out.println("After modification:");
System.out.println("Original Person: " + person1.name + ", " + person1.age + ", " + person1.address.street + ", " + person1.address.city);
System.out.println("Cloned Person: " + person2.name + ", " + person2.age + ", " + person2.address.street + ", " + person2.address.city);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
在这个示例中,Person
类和 Address
类都实现了 Cloneable
接口并重写了 clone()
方法。在 Person
类的 clone()
方法中,除了调用 super.clone()
来克隆自身,还手动克隆了 address
属性。这样,当修改克隆对象的 address
属性时,原对象的 address
属性不会受到影响。