在Java中,對象的拷貝分為淺拷貝和深拷貝兩種方式。
淺拷貝是指創建一個新的對象,然后將原對象的非靜態字段值復制到新對象中。新對象和原對象的引用類型字段將指向相同的對象。可以通過實現Cloneable
接口并重寫clone()
方法來實現淺拷貝。
深拷貝是指創建一個新的對象,然后將原對象的非靜態字段值復制到新對象中。新對象和原對象的引用類型字段也將被復制,即引用類型字段指向的對象也會被復制。可以通過實現Serializable
接口,將對象序列化為字節流,然后再反序列化為新對象來實現深拷貝。
下面是兩種拷貝方式的示例代碼:
class Person implements Cloneable {
private String name;
private int age;
private Address address;
// 省略構造方法和getter/setter
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Address {
private String city;
private String street;
// 省略構造方法和getter/setter
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("Beijing", "Dongcheng");
Person person1 = new Person("Alice", 25, address);
Person person2 = (Person) person1.clone();
System.out.println(person1 == person2); // false
System.out.println(person1.getAddress() == person2.getAddress()); // true
}
}
import java.io.*;
class Person implements Serializable {
private String name;
private int age;
private Address address;
// 省略構造方法和getter/setter
public Person deepCopy() throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (Person) ois.readObject();
}
}
class Address implements Serializable {
private String city;
private String street;
// 省略構造方法和getter/setter
}
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Address address = new Address("Beijing", "Dongcheng");
Person person1 = new Person("Alice", 25, address);
Person person2 = person1.deepCopy();
System.out.println(person1 == person2); // false
System.out.println(person1.getAddress() == person2.getAddress()); // false
}
}
需要注意的是,深拷貝要求被拷貝的對象及其引用類型字段都必須實現Serializable
接口。如果對象的某個引用類型字段沒有實現Serializable
接口,那么拷貝將會失敗。