- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
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 。
最后此篇关于详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)的文章就讲到这里了,如果你想了解更多关于详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
免责声明 这篇文章是关于术语“浅拷贝”和“深拷贝”的正确用法,特别是在谈论复制一个不包含任何引用的对象时。这个问题并不意味着(也不应该)基于意见,除非真的没有关于这个话题的共识。我已将此问题标记为 C
我有这个功能 int getrelation(string name, RELATION& output){ bool found=0; int index=0;
与 why should I make a copy of a data frame in pandas 有关 我注意到在流行的backtesting图书馆, def __init__(self, d
我的问题很基础,但我想 100% 理解所有内容。 SO中的很多问题都引用了我的帖子,但我没有找到满意的答案。 我们知道java中的枚举是引用类型。让我们考虑以下片段: public static cl
请引用这个 fiddle 的问题。 http://jsfiddle.net/AQR55/ 1)为什么附加到隔离范围属性的 watch - 双向绑定(bind)到父属性,不会在更改父范围属性时触发。 在
我想使用 UP3 来完成一项非常具体的任务,我应该能够使用 API 来实现该任务。我想了解是否可以编写以下应用程序。 基于https://jawbone.com/support/articles/00
如何在辅助方法中传递上下文并提取数据? 请参阅以下代码片段: import AppContext from '../../context/AppContext' import extractDatta
我正在尝试使用 simple-git 创建浅克隆。我正在尝试创建与此命令等效的命令:git clone --depth 1 https://github.com/steveukx/git-js.git
我是一名优秀的程序员,十分优秀!