Java中的對象拷貝可以分為淺拷貝和深拷貝兩種方式。淺拷貝只是復制了對象的基本屬性值,兩個變量指向同一個對象,對一個變量所指向的對象進行修改,另一個變量所指向的對象也會受到影響。深拷貝則是在堆內存中創建一份新的對象,并將原對象的屬性值復制到新對象中。
下面,我們來通過一些例子來進一步了解淺拷貝和深拷貝:
淺拷貝
class Person implements Cloneable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class TestShallowCopy { public static void main(String[] args) throws Exception { Person p1 = new Person("Tom", 20); Person p2 = (Person) p1.clone(); System.out.println(p1 == p2); //false,p1和p2是兩個不同的對象 System.out.println(p1.getName() == p2.getName()); //true,p1和p2指向同一個String對象 } }
上面的例子中,我們實現了Person類的Cloneable接口,并重寫了clone()方法,使其能夠被復制。在main方法中,我們首先創建了一個Person對象p1,然后通過clone()方法復制出一個新的對象p2。執行結果表明,p1和p2雖然是兩個不同的對象,但是其中的String屬性name指向同一個對象。
深拷貝
class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public static Person deepCopy(Person p) throws Exception{ ByteArrayOutputStream bao = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bao); oos.writeObject(p); ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (Person) ois.readObject(); } } public class TestDeepCopy { public static void main(String[] args) throws Exception { Person p1 = new Person("Tom", 20); Person p2 = Person.deepCopy(p1); System.out.println(p1 == p2); //false,p1和p2是兩個不同的對象 System.out.println(p1.getName() == p2.getName()); //false,p1和p2指向不同的String對象 } }
上面的例子中,我們在Person類中定義了一個深拷貝方法deepCopy(),該方法利用Java的序列化機制將原對象p序列化為字節數組,再反序列化出一份新的對象返回。在main方法中,我們首先創建了一個Person對象p1,然后調用deepCopy()方法復制出一個新的對象p2。執行結果表明,p1和p2是兩個不同的對象,且其中的String屬性name指向不同的對象。