Java中的對(duì)象拷貝分為淺拷貝和深拷貝兩種方式。在進(jìn)行對(duì)象拷貝的時(shí)候,需要注意對(duì)象內(nèi)部存在引用數(shù)據(jù)類型的情況,因?yàn)閱渭兊目截愔粫?huì)復(fù)制引用地址,而不會(huì)創(chuàng)建一個(gè)新的對(duì)象。下面我們具體介紹一下Java中如何進(jìn)行淺拷貝和深拷貝。
1. 淺拷貝
public class Person implements Cloneable { private String name; private int age; private Address addr; // 構(gòu)造方法 public Person(String name, int age, Address addr) { this.name = name; this.age = age; this.addr = addr; } // 克隆方法,實(shí)現(xiàn)淺拷貝 public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } } public class Address { private String city; // 構(gòu)造方法 public Address(String city) { this.city = city; } } public static void main(String[] args) { Address addr = new Address("Beijing"); Person p1 = new Person("Tom", 20, addr); Person p2 = (Person) p1.clone(); // 淺拷貝 System.out.println(p1.addr == p2.addr); // true }
在上述代碼中,我們定義了一個(gè)Person類和Address類。Person類中包含了一個(gè)Address類的引用addr,實(shí)現(xiàn)了Cloneable接口并重寫了clone()方法,實(shí)現(xiàn)了淺拷貝。在執(zhí)行p2 = (Person) p1.clone()時(shí),p2對(duì)象中的addr成員變量會(huì)復(fù)制p1對(duì)象中的addr成員變量的引用地址,兩者指向的是同一個(gè)對(duì)象。
2. 深拷貝
public class Person implements Serializable { private String name; private int age; private Address addr; // 構(gòu)造方法 public Person(String name, int age, Address addr) { this.name = name; this.age = age; this.addr = addr; } // 克隆方法,實(shí)現(xiàn)深拷貝 public Object deepClone() 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 ois.readObject(); } } public class Address implements Serializable{ private String city; // 構(gòu)造方法 public Address(String city) { this.city = city; } } public static void main(String[] args) throws IOException, ClassNotFoundException { Address addr = new Address("Beijing"); Person p1 = new Person("Tom", 20, addr); Person p2 = (Person) p1.deepClone(); // 深拷貝 System.out.println(p1.addr == p2.addr); // false }
在上述代碼中,我們實(shí)現(xiàn)了Serializable接口,通過(guò)ObjectOutputStream和ObjectInputStream實(shí)現(xiàn)了深拷貝。在執(zhí)行p2 = (Person) p1.deepClone()時(shí),p2對(duì)象中的addr成員變量會(huì)創(chuàng)建一個(gè)新的Address對(duì)象,從而達(dá)到深拷貝的目的。