在Java中,拷貝對象時通常使用深拷貝和淺拷貝。它們的主要區別是:
- 淺拷貝只復制原始對象的屬性的引用,而深拷貝則會復制整個子對象。
- 淺拷貝是指創建一個新對象,這個新對象具有原始對象的屬性。如果屬性是基本類型,則拷貝其值;如果屬性是引用類型,則拷貝其地址。
- 深拷貝是指創建一個新對象,這個新對象具有原始對象的非基本類型屬性的副本。即使原始對象具有對其他對象的引用,新對象也會為它們創建自己的副本。
淺拷貝示例:
public class Person implements Cloneable { private String name; private Address address; public Person(String name, Address address) { this.name = name; this.address = address; } public Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Address { private String location; public Address(String location) { this.location = location; } }
使用淺拷貝創建Person對象的副本:
Person person = new Person("Tom", new Address("Beijing")); Person clonePerson = (Person) person.clone(); System.out.println(person == clonePerson); // false System.out.println(person.getAddress() == clonePerson.getAddress()); // true
從輸出可以看出,原始對象person和其副本clonePerson的地址不同,但是它們的屬性address的地址相同,也就是說是淺拷貝。
深拷貝示例:
public class Person implements Serializable { private String name; private Address address; public Person(String name, Address address) { this.name = name; this.address = address; } public Person deepClone() throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (Person) ois.readObject(); } } public class Address implements Serializable { private String location; public Address(String location) { this.location = location; } }
使用深拷貝創建Person對象的副本:
Person person = new Person("Tom", new Address("Beijing")); Person clonePerson = person.deepClone(); System.out.println(person == clonePerson); // false System.out.println(person.getAddress() == clonePerson.getAddress()); // false
可以看出,深拷貝創建的副本完全是一個新對象,包括原始對象的所有屬性。
總之,深拷貝和淺拷貝在Java中都是很常見的,具備不同的自用場景。需要根據實際情況選擇使用哪種方式。