深克隆和潛克隆是Java中clone()方法中比較重要的概念。在進行克隆操作時,我們可能需要將對象的所有屬性都進行一遍拷貝,這就是深克隆。而有時候只需要拷貝一部分屬性,讓新的對象與原對象共享一些屬性,這就是潛克隆。
對于深克隆,一般需要重寫對象的clone()方法,并將對象所有的引用類型屬性也進行克隆拷貝。下面是一個示例:
public class Person implements Cloneable { private String name; private int age; private Address address; @Override protected Object clone() throws CloneNotSupportedException { Person person = (Person) super.clone(); person.address = (Address) address.clone(); return person; } // 省略getters和setters } public class Address implements Cloneable { private String city; private String street; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } // 省略getters和setters } // 測試代碼 Address address = new Address(); address.setCity("Beijing"); address.setStreet("Tian'anmen"); Person person1 = new Person(); person1.setName("Tom"); person1.setAge(18); person1.setAddress(address); Person person2 = (Person) person1.clone(); address.setStreet("Wangfujing"); System.out.println(person1.getAddress().getStreet()); // 輸出: Wangfujing System.out.println(person2.getAddress().getStreet()); // 輸出: Tian'anmen
可以看到,在調用person1的clone()方法時,person2的所有屬性都被進行了拷貝,包括address。而在address進行克隆時,對于它自身的屬性(city和street)就不需要進行深克隆,直接返回super.clone()即可。
相對于深克隆,潛克隆則簡單很多。只需要保持對象的引用類型屬性不被拷貝即可。下面是一個示例:
public class Person implements Cloneable { private String name; private int age; private Address address; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } // 省略getters和setters } public class Address { private String city; private String street; // 省略構造函數 // 省略getters和setters } // 測試代碼 Address address = new Address("Beijing", "Tian'anmen"); Person person1 = new Person(); person1.setName("Tom"); person1.setAge(18); person1.setAddress(address); Person person2 = (Person) person1.clone(); address.setStreet("Wangfujing"); System.out.println(person1.getAddress().getStreet()); // 輸出: Wangfujing System.out.println(person2.getAddress().getStreet()); // 輸出: Wangfujing
可以看到,在調用person1的clone()方法時,person2的所有屬性都被進行了拷貝,但address沒有進行深克隆,仍然與person1共享了同一個對象。因此對address屬性的修改會影響到person1和person2。