Java深度複製和淺度複製
淺複製(淺克隆):淺複製僅僅複製所考慮的對象,而不復制它所引用的對象。
深複製(深克隆):深複製把要複製的對象所引用的對象都複製了一遍。
Java中對象的克隆,爲了獲取對象的一份拷貝,我們可以利用Object類的clone()方法。必須要遵循下面三點 :
1.在派生類中覆蓋基類的clone()方法,並聲明爲public【Object類中的clone()方法爲protected的】。
2.在派生類的clone()方法中,調用super.clone()。
3.在派生類中實現Cloneable接口。
Object類裏的clone方法是淺複製(淺克隆)
淺複製(淺克隆)的例子如下:
package com.test;
1.public class DeepCloneTest {
2. public static void main(String[] args) throws Exception{
3. //teacher對象將不被clone出來的Student對象共享.
4. Teacher teacher = new Teacher();
5. teacher.setAge(40);
6. teacher.setName("Teacher zhang");
7.
8. Student student1 = new Student();
9. student1.setAge(20);
10. student1.setName("zhangsan");
11. student1.setTeacher(teacher);
13.//複製出來一個對象student2
14. Student student2 = (Student)student1.clone();
15. System.out.println(student2.getAge());
16. System.out.println(student2.getName());
17.
18.
19. System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
20. System.out.println(student1.getTeacher().getAge());
21. System.out.println(student1.getTeacher().getName());
22.
23.
24. //修改student2的引用對象
25. student2.getTeacher().setAge(50);
26. student2.getTeacher().setName("Teacher Li");
27.
28. System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
29. System.out.println(student1.getTeacher().getAge());
30. System.out.println(student1.getTeacher().getName());
31. }
32.}
1.class Teacher {
2. public int age;
3. public String name;
4.
5. public int getAge() {
6. return age;
7. }
8. public void setAge(int age) {
9. this.age = age;
10. }
11. public String getName() {
12. return name;
13. }
14. public void setName(String name) {
15. this.name = name;
16. }
輸出結果爲:
20
zhangsan
~~~~~~~~~~~~~~~~~~
40
Teacher zhang
~~~~~~~~~~~~~~~~~~
50
Teacher Li
2.深複製(深Clone)例子:
1.package com.test1;
2.//深clone
3.public class DeepCloneTest {
4. public static void main(String[] args) throws Exception{
5. //teacher對象將不被clone出來的Student對象共享.
6. Teacher teacher = new Teacher();
7. teacher.setAge(40);
8. teacher.setName("Teacher zhang");
9.
10. Student student1 = new Student();
11. student1.setAge(20);
12. student1.setName("zhangsan");
13. student1.setTeacher(teacher);
14.
15. //複製出來一個對象student2
16. Student student2 = (Student)student1.clone();
17. System.out.println(student2.getAge());
18. System.out.println(student2.getName());
19.
20.
21. System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
22. System.out.println(student1.getTeacher().getAge());
23. System.out.println(student1.getTeacher().getName());
24.
25.
26. //修改student2的引用對象
27. student2.getTeacher().setAge(50);
28. student2.getTeacher().setName("Teacher Li");
29.
30. System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
31. System.out.println(student1.getTeacher().getAge());
32. System.out.println(student1.getTeacher().getName());
33. }
34.}
35.class Teacher implements Cloneable{
36. public int age;
37. public String name;
38.
39. public int getAge() {
40. return age;
41. }
42. public void setAge(int age) {
43. this.age = age;
44. }
45. public String getName() {
46. return name;
47. }
48. public void setName(String name) {
49. this.name = name;
50. }
51. @Override
52. public Object clone() throws CloneNotSupportedException {
53. return super.clone();
54. }
55.
56.}
57.class Student implements Cloneable{
58.
59. public int age ;
60. public String name;
61. public Teacher teacher;
62. public int getAge() {
63. return age;
64. }
65. public void setAge(int age) {
66. this.age = age;
67. }
68. public String getName() {
69. return name;
70. }
71. public void setName(String name) {
72. this.name = name;
73. }
74. public Teacher getTeacher() {
75. return teacher;
76. }
77. public void setTeacher(Teacher teacher) {
78. this.teacher = teacher;
79. }
80. @Override
81. public Object clone() throws CloneNotSupportedException {
82. Student student = (Student)super.clone();
83. //將引用的對象teacher也clone下
84. student.setTeacher((Teacher)(student.getTeacher().clone()));
85. return student;
86. }
87.
88.
89.}
輸出結果爲:
20
zhangsan
~~~~~~~~~~~~~~~~~~
40
Teacher zhang
~~~~~~~~~~~~~~~~~~
40
Teacher zhang
## 利用序列化來做深複製,##
把對象寫到流裏的過程是序列化(Serilization)過程,而把對象從流中讀出來的過程則叫做反序列化(Deserialization)過程。應當指出的是,寫在流裏的是對象的一個拷貝,而原對象仍然存在於JVM裏面。利用這個特性,可以做深拷貝。
1.package com.test3;
2.import java.io.ByteArrayInputStream;
3.import java.io.ByteArrayOutputStream;
4.import java.io.ObjectInputStream;
5.import java.io.ObjectOutputStream;
6.import java.io.Serializable;
7.//利用序列化來做深複製
8.//深clone
9.public class DeepCloneTest {
10. public static void main(String[] args) throws Exception{
11. //teacher對象將不被clone出來的Student對象共享.
12. Teacher teacher = new Teacher();
13. teacher.setAge(40);
14. teacher.setName("Teacher zhang");
15.
16. Student student1 = new Student();
17. student1.setAge(20);
18. student1.setName("zhangsan");
19. student1.setTeacher(teacher);
20.
21. //複製出來一個對象student2
22. Student student2 = (Student)student1.deepCopy();
23. System.out.println(student2.getAge());
24. System.out.println(student2.getName());
25.
26.
27. System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
28. System.out.println(student1.getTeacher().getAge());
29. System.out.println(student1.getTeacher().getName());
30.
31.
32. //修改student2的引用對象
33. student2.getTeacher().setAge(50);
34. student2.getTeacher().setName("Teacher Li");
35.
36. System.out.println("~~~~~~~~~~~~~~~~~~~~~~");
37. System.out.println(student1.getTeacher().getAge());
38. System.out.println(student1.getTeacher().getName());
39. }
40.}
41.class Teacher implements Serializable{
42.
43. private static final long serialVersionUID = -8834559347461591191L;
44.
45. public int age;
46. public String name;
47.
48. public int getAge() {
49. return age;
50. }
51. public void setAge(int age) {
52. this.age = age;
53. }
54. public String getName() {
55. return name;
56. }
57. public void setName(String name) {
58. this.name = name;
59. }
60.
61.}
62.class Student implements Serializable{
63.
64. //serialVersionUID 如果你的對象序列化後存到硬盤上面後,可是後來你卻更改了類的field(增加或減少或改名),當你反序列化時,就會出現Exception的,這樣就會造成不兼容性的問題。
65. //但當serialVersionUID相同時,它就會將不一樣的field以type的缺省值賦值(如int型的是0,String型的是null等),這個可以避開不兼容性的問題。所以最好給serialVersionUID賦值
66. private static final long serialVersionUID = 7991552226614088458L;
67.
68. public int age ;
69. public String name;
70. public Teacher teacher;
71. public int getAge() {
72. return age;
73. }
74. public void setAge(int age) {
75. this.age = age;
76. }
77. public String getName() {
78. return name;
79. }
80. public void setName(String name) {
81. this.name = name;
82. }
83. public Teacher getTeacher() {
84. return teacher;
85. }
86. public void setTeacher(Teacher teacher) {
87. this.teacher = teacher;
88. }
89.
90. public Object deepCopy() throws Exception{
91. //將該對象序列化成流,因爲寫在流裏的是對象的一個拷貝,而原對象仍然存在於JVM裏面。所以利用這個特性可以實現對象的深拷貝
92. ByteArrayOutputStream bos = new ByteArrayOutputStream();
93. ObjectOutputStream oos = new ObjectOutputStream(bos);
94. oos.writeObject(this);
95. //將流序列化成對象
96. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
97. ObjectInputStream ois = new ObjectInputStream(bis);
98. return ois.readObject();
99. }
102.}
輸出結果爲:
20
zhangsan
~~~~~~~~~~~~~~~~~~
40
Teacher zhang
~~~~~~~~~~~~~~~~~~
40
Teacher zhang