克隆是Java中常用的一項技術,通過克隆可以復制一個對象,并生成一個與原對象內容完全一致的新對象。由于Java中存在深克隆和淺克隆兩種不同的克隆方式,因此本文將介紹Java中深克隆和淺克隆實現的方法以及它們之間的區別。
首先,我們來介紹Java中的淺克隆。當使用淺克隆實現一個對象的復制時,只會復制它的引用類型和基本數據類型,而不會復制它引用的對象。以一個簡單的例子來說明:
public class Sheep implements Cloneable { private String name; private int age; private Listtags; public Sheep(String name, int age, List tags) { this.name = name; this.age = age; this.tags = tags; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { List tags = new ArrayList<>(); tags.add("cute"); tags.add("fluffy"); Sheep sheep1 = new Sheep("Dolly", 2, tags); Sheep sheep2 = (Sheep) sheep1.clone(); System.out.println(sheep1.getName() == sheep2.getName()); // true System.out.println(sheep1.getAge() == sheep2.getAge()); // true System.out.println(sheep1.getTags() == sheep2.getTags()); // true } }
可以看到,在上面的例子中,我們定義了一個Sheep類作為被克隆的對象,其中包含一個成員變量tags,它是一個字符串類型的List。在使用淺克隆實現對象復制時,只會復制該對象的成員變量的值,但不會復制該對象的成員變量引用的對象。因此,當我們打印出sheep1和sheep2的tags屬性時,它們是相等的,但是它們的引用是不同的。
接下來,我們來介紹Java中的深克隆實現方法。與淺克隆不同,深克隆會完整地復制對象,包括該對象所有的基本數據類型和引用類型成員變量。下面是使用深克隆實現對象復制的代碼示例:
public class Sheep implements Cloneable { private String name; private int age; private Listtags; public Sheep(String name, int age, List tags) { this.name = name; this.age = age; this.tags = tags; } public Object 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 ois.readObject(); } public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException { List tags = new ArrayList<>(); tags.add("cute"); tags.add("fluffy"); Sheep sheep1 = new Sheep("Dolly", 2, tags); Sheep sheep2 = (Sheep) sheep1.deepClone(); System.out.println(sheep1.getName() == sheep2.getName()); // false System.out.println(sheep1.getAge() == sheep2.getAge()); // true System.out.println(sheep1.getTags() == sheep2.getTags()); // false } }
可以看到,在使用深克隆實現對象復制時,需要將該對象先寫入到一個輸出流中,再從輸入流中讀取出來,這樣就能夠完整地復制對象了。在上述示例中,我們通過ByteArrayOutputStream、ObjectOutputStream、ByteArrayInputStream和ObjectInputStream等類實現了深克隆的功能。最后,當我們比較sheep1和sheep2的tags屬性時,它們的值和引用都是不相同的,因為進行了深克隆。