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