在Java中,對象的復制可以分為深拷貝和淺拷貝。對于一個對象,如果我們想要它在內存中完全獨立,我們需要進行深拷貝。相反,如果我們只是想讓兩個變量指向同一個對象,我們可以進行淺拷貝。我們使用不同的方法來實現這兩種拷貝。
淺拷貝復制的是引用地址,也就是將一個對象的內存地址傳給另一個對象,使得兩個對象指向的是同一塊內存空間。簡單示例如下:
public class Person { public int age; public String name; public Listhobbies; public Person(int age, String name, List hobbies) { this.age = age; this.name = name; this.hobbies = hobbies; } // 重寫clone方法 @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Test { public static void main(String[] args) throws CloneNotSupportedException { List hobbies = new ArrayList<>(); hobbies.add("playing games"); hobbies.add("reading"); Person p1 = new Person(25, "Alice", hobbies); Person p2 = (Person) p1.clone(); System.out.println(p1 == p2); // false System.out.println(p1.hobbies == p2.hobbies); // true,淺拷貝的結果 } }
我們可以看到,使用clone方法進行對象復制時,得到的是淺拷貝的結果。
相反,深拷貝是將一個對象完整地復制到新的內存空間,即在棧區和堆區都分別分配內存。在Java中,我們可以使用多種方法來實現深拷貝,例如使用序列化、使用BeanUtils等工具類。示例代碼如下:
public class Person implements Serializable { public int age; public String name; public Listhobbies; public Person(int age, String name, List hobbies) { this.age = age; this.name = name; this.hobbies = hobbies; } // 通過序列化實現深拷貝 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 class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { List hobbies = new ArrayList<>(); hobbies.add("playing games"); hobbies.add("reading"); Person p1 = new Person(25, "Alice", hobbies); Person p2 = (Person) p1.deepClone(); System.out.println(p1 == p2); // false System.out.println(p1.hobbies == p2.hobbies); // false,深拷貝的結果 } }
通過使用序列化,我們實現了一個完全獨立的新對象,即深拷貝的結果。