1.序列化實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class CloneUtils { @SuppressWarnings ( "unchecked" ) public static <T extends Serializable> T clone(T object){ T cloneObj = null ; try { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(out); obs.writeObject(object); obs.close(); ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(ios); cloneObj = (T) ois.readObject(); } catch (Exception e){ e.printStackTrace(); } return cloneObj; } } |
2.主代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
public class TestString { public static void main(String[] args) { TestString test = new TestString(); System.out.println( "-------淺拷貝---------" ); test.qianCopyTest(); System.out.println(); System.out.println( "--------使用clone深拷貝--------" ); test.defaultCloneTest(); System.out.println(); System.out.println( "--------使用序列化實現對象的拷貝--------" ); test.streamClonrTest(); System.out.println( "--------耗時對比--------" ); System.out.println( "耗時1 : " + test.qianCopyCost()); System.out.println( "耗時2 : " + test.CloneCopyCost()); System.out.println( "耗時3 : " + test.StreamCopyCost()); } /*淺拷貝*/ private void qianCopyTest() { String s = "cd"; change(s); System.out.println(s); System.out.println("----------------"); String b = new String("cd"); change(b); System.out.println(b); System.out.println("----------------"); int me = 1; change(me); System.out.println(me); System.out.println("----------------"); Person person = new Person("我", 13,new Email("我")); change(person); System.out.println(person.toString()); } /*使用默認的clone方法,需要Person實現Cloneable接口*/ private void defaultCloneTest(){ Person person = new Person("我", 13,new Email("我")); Person person1 = person.clone(); Person person2 = person.clone(); System.out.println("person : 【"+person+"】"); System.out.println("person1 : 【"+person1+"】"); System.out.println("person2 : 【"+person2+"】"); //改一個就會觸動全部!! 這就是使用默認的clone方法的弊端 /*該clone()方法是使用Object類的clone()方法,但是該方法存在一個缺陷,它并不會將對象的所有屬性全部拷貝過來,而是有選擇性的拷貝,基本規則如下: 1、 基本類型 如果變量是基本很類型,則拷貝其值,比如int、float等。 2、 對象 如果變量是一個實例對象,則拷貝其地址引用,也就是說此時新對象與原來對象是公用該實例變量。 3、 String字符串 若變量為String字符串,則拷貝其地址引用。但是在修改時,它會從字符串池中重新生成一個新的字符串,原有紫都城對象保持不變。*/ person.getEmail().setContent("你"); System.out.println("之后的person : 【"+person+"】"); System.out.println("之后的person1 : 【"+person1+"】"); System.out.println("之后的person2 : 【"+person2+"】"); } /*使用序列化實現對象的拷貝,需要對象以及對象中的其他對象都要實現Serializable接口*/ private void streamClonrTest(){ Person person = new Person("我", 13,new Email("我")); Person person1 = CloneUtils.clone(person); Person person2 = CloneUtils.clone(person); System.out.println("person : 【"+person+"】"); System.out.println("person1 : 【"+person1+"】"); System.out.println("person2 : 【"+person2+"】"); person.getEmail().setContent("你"); System.out.println("之后的person : 【"+person+"】"); System.out.println("之后的person1 : 【"+person1+"】"); System.out.println("之后的person2 : 【"+person2+"】"); } private static void change(String x) { x = "ab"; } private static void change(int x) { x = 2; } private static void change(Person x) { x = new Person("你", 20, new Email("你")); } private long qianCopyCost(){ long start = System.currentTimeMillis(); Person person = new Person("我", 13,new Email("我")); List<Person> list = new ArrayList<>(); for(int i = 0;i<=10000;i++){ list.add(new Person("你", 20, new Email("你"))); } return System.currentTimeMillis()-start; } private long CloneCopyCost(){ long start = System.currentTimeMillis(); Person person = new Person("我", 13,new Email("我")); List<Person> list = new ArrayList<>(); for(int i = 0;i<=10000;i++){ list.add(person.clone()); } return System.currentTimeMillis()-start; } private long StreamCopyCost(){ long start = System.currentTimeMillis(); Person person = new Person("我", 13,new Email("我")); List<Person> list = new ArrayList<>(); for(int i = 0;i<=10000;i++){ list.add(CloneUtils.clone(person)); } return System.currentTimeMillis()-start; } } class Person implements Serializable, Cloneable { private static final long serialVersionUID = -8584225043397465132L; private String name; private int age; public void setEmail(Email email) { this.email = email; } private Email email; public Email getEmail() { return email; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public Person(String name, int age, Email email) { this.name = name; this.age = age; this.email = email; } @Override public String toString() { return "name : " + name + " | age : " + age +" | content : "+email.getContent(); } @Override protected Person clone() { Person person = null; try { person = (Person) super.clone(); /*如果加上下一行 “使用clone深拷貝” 就不會改一處其他都改變了*/ person.setEmail( new Email(person.getEmail().getContent())); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; } } class Email implements Serializable { private static final long serialVersionUID = 1426052929769365539L; private String content; public void setContent(String content) { this .content = content; } public String getContent() { return content; } public Email(String content) { this .content = content; } } |
測試了一下時間:
輸出:
-------淺拷貝---------
cd
cd
1
name : 我 | age : 13 | content : 我
--------使用clone深拷貝--------
person : 【name : 我 | age : 13 | content : 我】
person1 : 【name : 我 | age : 13 | content : 我】
person2 : 【name : 我 | age : 13 | content : 我】
之后的person : 【name : 我 | age : 13 | content : 你】
之后的person1 : 【name : 我 | age : 13 | content : 我】
之后的person2 : 【name : 我 | age : 13 | content : 我】
--------使用序列化實現對象的拷貝--------
person : 【name : 我 | age : 13 | content : 我】
person1 : 【name : 我 | age : 13 | content : 我】
person2 : 【name : 我 | age : 13 | content : 我】
之后的person : 【name : 我 | age : 13 | content : 你】
之后的person1 : 【name : 我 | age : 13 | content : 我】
之后的person2 : 【name : 我 | age : 13 | content : 我】
--------耗時對比--------
耗時1 : 2
耗時2 : 1
耗時3 : 338
以上所述是小編給大家介紹的java中的深拷貝和淺拷貝(clone()方法的重寫、使用序列化實現真正的深拷貝)詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:https://blog.csdn.net/changshuchao/article/details/88406171