原文鏈接: http://blog.csdn.net/jdluojing/article/details/6963112
1.java里的clone分為:
A:淺復制(淺克隆): 淺復制僅僅復制所考慮的對象,而不復制它所引用的對象。
b:深復制(深克隆):深復制把要復制的對象所引用的對象都復制了一遍。
Java中對象的克隆,為了獲取對象的一份拷貝,我們可以利用Object類的clone()方法。必須要遵循下面三點
1.在派生類中覆蓋基類的clone()方法,並聲明為public【Object類中的clone()方法為protected的】。
2.在派生類的clone()方法中,調用super.clone()。
3.在派生類中實現Cloneable接口。
Object類里的clone方法是淺復制(淺克隆)
淺復制(淺克隆)的例子如下:
- public class CloneTest
- {
- public static void main(String[] args) throws Exception
- {
- // teacher對象將被clone出來的Student對象共享.
- Teacher teacher = new Teacher();
- teacher.setAge(40);
- teacher.setName("Teacher zhang");
- Student student1 = new Student();
- student1.setAge(20);
- student1.setName("zhangsan");
- student1.setTeacher(teacher);
- // 復制出來一個對象student2
- Student student2 = (Student) student1.clone();
- System.out.println(student2.getAge());
- System.out.println(student2.getName());
- System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
- System.out.println(student1.getTeacher().getAge());
- System.out.println(student1.getTeacher().getName());
- // 修改student2的引用對象
- student2.getTeacher().setAge(50);
- student2.getTeacher().setName("Teacher Li");
- System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
- System.out.println(student1.getTeacher().getAge());
- System.out.println(student1.getTeacher().getName());
- }
- }
- class Teacher
- {
- public int age;
- public String name;
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- }
- class Student implements Cloneable
- {
- public int age;
- public String name;
- public Teacher teacher;
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- public Teacher getTeacher()
- {
- return teacher;
- }
- public void setTeacher(Teacher teacher)
- {
- this.teacher = teacher;
- }
- @Override
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
- }
- 輸出結果為:
- 20
- zhangsan
- ~~~~~~~~~~~~~~~~~~~~~~
- 40
- Teacher zhang
- ~~~~~~~~~~~~~~~~~~~~~~
- 50
- Teacher Li
2.深復制(深Clone)例子:
- public class DeepCloneTest
- {
- public static void main(String[] args) throws Exception
- {
- // teacher對象將不被clone出來的Student對象共享.
- Teacher teacher = new Teacher();
- teacher.setAge(40);
- teacher.setName("Teacher zhang");
- Student student1 = new Student();
- student1.setAge(20);
- student1.setName("zhangsan");
- student1.setTeacher(teacher);
- // 復制出來一個對象student2
- Student student2 = (Student) student1.clone();
- System.out.println(student2.getAge());
- System.out.println(student2.getName());
- System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
- System.out.println(student1.getTeacher().getAge());
- System.out.println(student1.getTeacher().getName());
- // 修改student2的引用對象
- student2.getTeacher().setAge(50);
- student2.getTeacher().setName("Teacher Li");
- System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
- System.out.println(student1.getTeacher().getAge());
- System.out.println(student1.getTeacher().getName());
- }
- }
- class Teacher implements Cloneable
- {
- public int age;
- public String name;
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- @Override
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
- }
- class Student implements Cloneable
- {
- public int age;
- public String name;
- public Teacher teacher;
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- public Teacher getTeacher()
- {
- return teacher;
- }
- public void setTeacher(Teacher teacher)
- {
- this.teacher = teacher;
- }
- @Override
- public Object clone() throws CloneNotSupportedException
- {
- Student student = (Student) super.clone();
- // 將引用的對象teacher也clone下
- student.setTeacher((Teacher) (student.getTeacher().clone()));
- return student;
- }
- }
- 輸出結果為:
- 20
- zhangsan
- ~~~~~~~~~~~~~~~~~~~~~~
- 40
- Teacher zhang
- ~~~~~~~~~~~~~~~~~~~~~~
- 40
- Teacher zhang
3.利用序列化來做深復制,把對象寫到流里的過程是序列化(Serilization)過程,而把對象從流中讀出來的過程則叫做反序列化(Deserialization)過程。應當指出的是,寫在流里的是對象的一個拷貝,而原對象仍然存在於JVM里面。,利用這個特性,可以做深拷貝 。
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.Serializable;
- //利用序列化來做深復制
- //深clone
- public class DeepCloneTest
- {
- public static void main(String[] args) throws Exception
- {
- // teacher對象將不被clone出來的Student對象共享.
- Teacher teacher = new Teacher();
- teacher.setAge(40);
- teacher.setName("Teacher zhang");
- Student student1 = new Student();
- student1.setAge(20);
- student1.setName("zhangsan");
- student1.setTeacher(teacher);
- // 復制出來一個對象student2
- Student student2 = (Student) student1.deepCopy();
- System.out.println(student2.getAge());
- System.out.println(student2.getName());
- System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
- System.out.println(student1.getTeacher().getAge());
- System.out.println(student1.getTeacher().getName());
- // 修改student2的引用對象
- student2.getTeacher().setAge(50);
- student2.getTeacher().setName("Teacher Li");
- System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
- System.out.println(student1.getTeacher().getAge());
- System.out.println(student1.getTeacher().getName());
- }
- }
- class Teacher implements Serializable
- {
- private static final long serialVersionUID = -8834559347461591191L;
- public int age;
- public String name;
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- }
- class Student implements Serializable
- {
- // serialVersionUID
- // 如果你的對象序列化后存到硬盤上面后,可是后來你卻更改了類的field(增加或減少或改名),當你反序列化時,就會出現Exception的,這樣就會造成不兼容性的問題。
- // 但當serialVersionUID相同時,它就會將不一樣的field以type的缺省值賦值(如int型的是0,String型的是null等),這個可以避開不兼容性的問題。所以最好給serialVersionUID賦值
- private static final long serialVersionUID = 7991552226614088458L;
- public int age;
- public String name;
- public Teacher teacher;
- public int getAge()
- {
- return age;
- }
- public void setAge(int age)
- {
- this.age = age;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- public Teacher getTeacher()
- {
- return teacher;
- }
- public void setTeacher(Teacher teacher)
- {
- this.teacher = teacher;
- }
- public Object deepCopy() throws Exception
- {
- // 將該對象序列化成流,因為寫在流里的是對象的一個拷貝,而原對象仍然存在於JVM里面。所以利用這個特性可以實現對象的深拷貝
- 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();
- }
- }
- 輸出結果為:
- 20
- zhangsan
- ~~~~~~~~~~~~~~~~~~~~~~
- 40
- Teacher zhang
- ~~~~~~~~~~~~~~~~~~~~~~
- 40
- Teacher zhang