Java中对象的深克隆和浅克隆
2019獨角獸企業重金招聘Python工程師標準>>>
淺克隆和深克隆的概念
????????淺克隆:被克隆的對象里的所有變量值都與原來的對象相同,而所有對其他對象的引用仍然指向原來的對象。簡而言之,淺克隆僅僅克隆當前對象,而不克隆當前對象所引用的對象。
????????深克隆:被克隆的對象里的所有變量值都與原來的對象相同,那些引用其他對象的變量將指向被復制過的新對象,而不再是原來被引用的對象。簡而言之,深克隆不僅克隆了當前對象,還把當前對象所引用的對象都復制了一遍。
?
Java中的clone()方法
????? ? Object類中的clone()方法屬于淺克隆。它的工作原理是:先在內存中開辟一塊和原始對象相同大小的空間,然后原樣復制原始對象中的內容。對于基本數據類型,這樣操作是沒問題的。但對于非基本數據類型,由于它們所保存的僅僅是對象的引用,如果不進行更深層次的克隆,就會導致克隆后的對象引用和原始對象中相應的對象引用所指向的是同一個對象。
?
使用clone()方法實現淺克隆
????? ? 在要克隆的類中實現Cloneable接口,覆蓋Object類中的clone()方法,并聲明為public。同時在clone()方法中,調用super.clone()返回克隆后的對象。請看以下代碼:
class Professor {String name;int age;public Professor(String name, int age) {this.name = name;this.age = age;} }class Student implements Cloneable {String name;int age;Professor professor;public Student(String name, int age, Professor professor) {this.name = name;this.age = age;this.professor = professor;}@Overrideprotected Student clone() throws CloneNotSupportedException {return (Student) super.clone();} }public class CloneTutorial {public static void main(String[] args) throws CloneNotSupportedException {Professor professor = new Professor("Galler", 50);Student student1 = new Student("Tom", 18, professor);Student student2 = student1.clone();System.out.println("Before change student2's professor");System.out.println("Student1's professor name = " + student1.professor.name);System.out.println("student1's professor age = " + student1.professor.age);student2.professor.name = "Mary";student2.professor.age = 30;System.out.println();System.out.println("After change student2's professor");System.out.println("Student1's professor name = " + student1.professor.name);System.out.println("Student1's professor age = " + student1.professor.age);} }?
使用clone()方法實現深克隆
? ? ? ? 通過以上代碼可以證明Java中的clone()方法是淺克隆,那應該如何實現更深層次的克隆呢?請看以下代碼:
class Professor implements Cloneable {String name;int age;public Professor(String name, int age) {this.name = name;this.age = age;}@Overrideprotected Professor clone() throws CloneNotSupportedException {return (Professor) super.clone();} }class Student implements Cloneable {String name;int age;Professor professor;public Student(String name, int age, Professor professor) {this.name = name;this.age = age;this.professor = professor;}@Overrideprotected Student clone() throws CloneNotSupportedException {Student student = (Student) super.clone();student.professor = student.professor.clone();return student;} }public class CloneTutorial {public static void main(String[] args) throws CloneNotSupportedException {Professor professor = new Professor("Galler", 50);Student student1 = new Student("Tom", 18, professor);Student student2 = student1.clone();System.out.println("Before change student2's professor");System.out.println("Student1's professor name = " + student1.professor.name);System.out.println("student1's professor age = " + student1.professor.age);student2.professor.name = "Mary";student2.professor.age = 30;System.out.println();System.out.println("After change student2's professor");System.out.println("Student1's professor name = " + student1.professor.name);System.out.println("Student1's professor age = " + student1.professor.age);} }? ? ? ? 在以上代碼中,雖然通過在Student類中調用Professor類中覆蓋的clone方法來對professor成員進行克隆從而實現了深克隆,但也由此可見,如果克隆類中的引用類型變量有多個的情況下,采用這種方式實現深克隆將會非常復雜。
?
使用對象序列化和反序列化實現深克隆(推薦)
????? ? 把對象寫到字節流里的過程是序列化(Serilization)的過程,而把對象從字節流中讀出來的過程是反序列化(Deserialization)的過程。由于在Java 序列化的過程中,寫在流里的是對象的一個拷貝,而原對象仍然在JVM里,所以可以利用這個原理來實現對對象的深克隆。請看以下代碼:
class Professor implements Serializable {String name;int age;public Professor(String name, int age) {this.name = name;this.age = age;} }class Student implements Serializable {String name;int age;Professor professor;public Student(String name, int age, Professor professor) {this.name = name;this.age = age;this.professor = professor;}public Student deepClone() throws Exception {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);objectOutputStream.writeObject(this);ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);return (Student) objectInputStream.readObject();} }public class CloneTutorial {public static void main(String[] args) throws Exception {Professor professor = new Professor("Galler", 50);Student student1 = new Student("Tom", 18, professor);Student student2 = student1.deepClone();System.out.println("Before change student2's professor");System.out.println("Student1's professor name = " + student1.professor.name);System.out.println("student1's professor age = " + student1.professor.age);student2.professor.name = "Mary";student2.professor.age = 30;System.out.println();System.out.println("After change student2's professor");System.out.println("Student1's professor name = " + student1.professor.name);System.out.println("Student1's professor age = " + student1.professor.age);} }?
總結
? ? ? ? 雖然使用Java的clone()方法實現淺克隆以及深克隆更加直觀,但是針對每一個需要克隆的類都必須單獨實現一個clone()方法,導致其擴展性并不好。而使用對象序列化與反序列化來實現深克隆,能使代碼更簡潔,更通用。此處推薦使用后者。
轉載于:https://my.oschina.net/zhaojia/blog/735432
總結
以上是生活随笔為你收集整理的Java中对象的深克隆和浅克隆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【有感而发】
- 下一篇: centos6.5环境下zookeepe