- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java Clone深拷贝与浅拷贝的两种实现方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
1.首先,你要知道怎么实现克隆:实现cloneable接口,在bean里面重写clone()方法,权限为public。 2.其次,你要大概知道什么是地址传递,什么是值传递。 3.最后,你要知道你为什么使用这个clone方法.
先看第一条,简单的克隆代码的实现。这个也就是我们在没了解清楚这个java的clone的时候,会出现的问题.
看完代码,我再说明这个时候的问题.
先看我要克隆的学生bean的代码:
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
|
package
com.lxk.model;
/**
* 学生类:有2个属性:1,基本属性-string-name;2,引用类型-car-car。
* <p>
* created by lxk on 2017/3/23
*/
public
class
student
implements
cloneable {
private
string name;
private
car car;
public
string getname() {
return
name;
}
public
void
setname(string name) {
this
.name = name;
}
public
car getcar() {
return
car;
}
public
void
setcar(car car) {
this
.car = car;
}
@override
public
string tostring() {
return
"student{"
+
"name='"
+ name + '\
''
+
", car="
+ car +
'}'
;
}
@override
public
student clone() {
student student =
null
;
try
{
student = (student)
super
.clone();
}
catch
(clonenotsupportedexception ignored) {
system.out.println(ignored.getmessage());
}
return
student;
}
}
|
学生内部引用了car这个bean 。
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
|
package
com.lxk.model;
import
java.util.list;
public
class
car
implements
comparable<car> {
private
string sign;
private
int
price;
private
list<dog> mydog;
private
list<string> boys;
public
car() {
}
public
car(string sign,
int
price) {
this
.sign = sign;
this
.price = price;
}
public
car(string sign,
int
price, list<dog> mydog) {
this
.sign = sign;
this
.price = price;
this
.mydog = mydog;
}
public
car(string sign,
int
price, list<dog> mydog, list<string> boys) {
this
.sign = sign;
this
.price = price;
this
.mydog = mydog;
this
.boys = boys;
}
public
string getsign() {
return
sign;
}
public
void
setsign(string sign) {
this
.sign = sign;
}
public
int
getprice() {
return
price;
}
public
void
setprice(
int
price) {
this
.price = price;
}
public
list<dog> getmydog() {
return
mydog;
}
public
void
setmydog(list<dog> mydog) {
this
.mydog = mydog;
}
public
list<string> getboys() {
return
boys;
}
public
void
setboys(list<string> boys) {
this
.boys = boys;
}
@override
public
int
compareto(car o) {
//同理也可以根据sign属性排序,就不举例啦。
return
this
.getprice() - o.getprice();
}
@override
public
string tostring() {
return
"car{"
+
"sign='"
+ sign + '\
''
+
", price="
+ price +
", mydog="
+ mydog +
", boys="
+ boys +
'}'
;
}
}
|
最后就是main测试类 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
com.lxk.findbugs;
import
com.lxk.model.car;
import
com.lxk.model.student;
/**
* 引用传递也就是地址传递需要注意的地方,引起的bug
* <p>
* created by lxk on 2017/3/23
*/
public
class
bug2 {
public
static
void
main(string[] args) {
student student1 =
new
student();
car car =
new
car(
"oooo"
,
100
);
student1.setcar(car);
student1.setname(
"lxk"
);
//克隆完之后,student1和student2应该没关系的,修改student1不影响student2的值,但是完之后发现,你修改car的值,student2也受影响啦。
student student2 = student1.clone();
system.out.println(
"学生2:"
+ student2);
//先输出student2刚刚克隆完之后的值,然后在修改student1的相关引用类型的属性值(car)和基本属性值(name)
car.setsign(
"x5"
);
student1.setname(
"xxx"
);
system.out.println(
"学生2:"
+ student2);
//再次输出看修改的结果
}
}
|
之后就该是执行的结果图了:
对上面执行结果的疑惑,以及解释说明:
我们可能觉得自己在bean里面实现clone接口,重写了这个clone方法,那么学生2是经由学生1clone,复制出来的, 那么学生1和学生2,应该是毫不相干的,各自是各自,然后,在修改学生1的时候,学生2是不会受影响的.
但是结果,不尽人意。从上图执行结果可以看出来,除了名字,这个属性是没有被学生1影响,关于car的sign属性已经因为学生1的变化而变化,这不是我希望的结果.
可见,这个简单的克隆实现也仅仅是个“浅克隆”,也就是基本类型数据,他是会给你重新复制一份新的,但是引用类型的,他就不会重新复制份新的。引用类型包括,上面的其他bean的引用,list集合,等一些引用类型.
那么怎么实现深克隆呢?
对上述代码稍作修改,如下: 学生bean的clone重写方法如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@override
public
student clone() {
student student =
null
;
try
{
student = (student)
super
.clone();
if
(car !=
null
) {
student.setcar(car.clone());
}
}
catch
(clonenotsupportedexception ignored) {
system.out.println(ignored.getmessage());
}
return
student;
}
|
然后还要car类实现cloneable接口,复写clone方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@override
public
car clone() {
car car =
null
;
try
{
car = (car)
super
.clone();
if
(mydog !=
null
) {
car.setmydog(lists.newarraylist(mydog));
}
if
(boys !=
null
) {
car.setboys(lists.newarraylist(boys));
}
}
catch
(clonenotsupportedexception ignored) {
system.out.println(ignored.getmessage());
}
return
car;
}
|
主测试代码不动,这个时候的执行结果如下:
可以看到,这个时候,你再修改学生1的值,就不会影响到学生2的值,这才是真正的克隆,也就是所谓的深克隆.
怎么举一反三?
可以看到,这个例子里面的引用类型就一个car类型的属性,但是实际开发中,除了这个引用其他bean类型的属性外,可能还要list类型的属性值用的最多.
那么要怎么深克隆呢,就像我在car bean类里面做的那样,把所有的引用类型的属性,都在clone一遍。那么你在最上层调用这个clone方法的时候,他就是真的深克隆啦.
我代码里面那么判断是为了避免空指针异常。当然,这个你也得注意咯.
注意 重写clone方法的时候,里面各个属性的null的判断哦.
上面的是override clone()方法来实现深克隆的。如果你这个要克隆的对象很复杂的话,你就不得不去每个引用到的对象去复写这个clone方法,这个太啰嗦来,改的地方,太多啦.
还有个方法就是使用序列化来实现这个深拷贝 。
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
|
/**
* 对象的深度克隆,此处的对象涉及collection接口和map接口下对象的深度克隆
* 利用序列化和反序列化的方式进行深度克隆对象
*
* @param object 待克隆的对象
* @param <t> 待克隆对象的数据类型
* @return 已经深度克隆过的对象
*/
public
static
<t
extends
serializable> t deepcloneobject(t object) {
t deepclone =
null
;
bytearrayoutputstream baos =
null
;
objectoutputstream oos =
null
;
bytearrayinputstream bais =
null
;
objectinputstream ois =
null
;
try
{
baos =
new
bytearrayoutputstream();
oos =
new
objectoutputstream(baos);
oos.writeobject(object);
bais =
new
bytearrayinputstream(baos
.tobytearray());
ois =
new
objectinputstream(bais);
deepclone = (t)ois.readobject();
}
catch
(ioexception | classnotfoundexception e) {
e.printstacktrace();
}
finally
{
try
{
if
(baos !=
null
) {
baos.close();
}
}
catch
(ioexception e) {
e.printstacktrace();
}
try
{
if
(oos !=
null
) {
oos.close();
}
}
catch
(ioexception e) {
e.printstacktrace();
}
try
{
if
(bais !=
null
) {
bais.close();
}
}
catch
(ioexception e) {
e.printstacktrace();
}
try
{
if
(ois !=
null
) {
ois.close();
}
}
catch
(ioexception e) {
e.printstacktrace();
}
}
return
deepclone;
}
|
具体的使用如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/**
* 使用序列化来实现深拷贝简单。但是,所涉及到的所有对象都的实现序列化接口。
*/
private
static
void
clonebyserializable() {
student student1 =
new
student();
car car =
new
car(
"oooo"
,
100
, lists.newarraylist(
new
dog(
"aaa"
,
true
,
true
)));
student1.setcar(car);
student1.setname(
"lxk"
);
student student2 = deepcloneobject(student1);
system.out.println(
"学生2:"
+ student2);
car.setsign(
"x5"
);
car.setmydog(
null
);
student1.setname(
"xxx"
);
system.out.println(
"学生2:"
+ student2);
}
|
实现的效果,还是和上面的一样的,但是这个就简单多来,只需要给涉及到的每个引用类型,都去实现序列化接口就好啦.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我的支持。如果你想了解更多相关内容请查看下面相关链接 。
原文链接:https://blog.csdn.net/qq_27093465/article/details/65443355 。
最后此篇关于Java Clone深拷贝与浅拷贝的两种实现方法的文章就讲到这里了,如果你想了解更多关于Java Clone深拷贝与浅拷贝的两种实现方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
什么是 vb6 或 java 中的对象克隆?我们在什么情况下使用克隆?克隆对象是什么意思?谁能用例子告诉我。 最佳答案 克隆实际上是将对象数据复制到新对象中。 此示例不克隆数据: Foo p = ne
ArrayList a=new ArrayList(); a.add(5); ArrayList b=(ArrayList)a.clone(); a.add(6); System.out.printl
这个问题在这里已经有了答案: Why does cloned() allow this function to compile (1 个回答) 关闭 3 个月前。 假设我们有一个可以克隆的某种类型的
我有这样的代码,我需要在其中将某些内容插入到两个单独的 HashMap 中。我只想要实现克隆的通用类型。 use std::collections::HashMap; use std::clone::
这段代码(also on play) use std::sync::Arc; struct Foo { x: isize, // Something complex in actual cod
我有按钮 Drag to insert h1 tag 当你拖动它时,我希望按钮留在原来的位置,助手是 Example在你放下它的地方,你会放下h1没有任何可拖动或 jQuery UI 样式的标记。 所
覆盖 clone 方法,而不实现 Cloneable 接口(interface)并且不调用 super.clone() 是一个好习惯。这样,就不会抛出 CloneNotSupportedExcepti
public abstract class Shape implements Cloneable { private String id; protected String type;
克隆远程仓库后,它不会通过 -a 选项显示任何远程分支。可能是什么问题呢?如何调试呢?在此片段中,未显示两个远程分支: $ git clone --depth 1 git://git.savannah
我看过这个答案for a git clone error ,建议不要克隆整个 repo,而是只克隆最新的提交,然后使用 unshallow 获取其余的提交。 考虑以下两个命令 1. git clone
当在网上搜索如何以多态方式深层复制对象的可能性时,我发现了 solution声称可以使用 clone() 方法解决许多问题,例如无法克隆 final 字段。该解决方案结合了在 clone() 实现中使
我正在尝试创建一个动态表单来向业务合作伙伴展示。 目标是能够在单击按钮时根据需要添加选择元素。但是,当它被点击时,它会复制模板两次,而不是一次。 这里只是我尝试过的代码的一些变体和 here is t
我知道实现 Object#clone() 的约定表明您应该调用 super.clone() 来获取复制的对象。 但我只是想知道如果我不这样做的话会有什么后果。让我们假设这个例子: class Some
我所说的示例:http://jsfiddle.net/bsnxp/1/ 如果你检查源 .show().clone() display 是 inline-block (它应该是什么)并且 .clone(
我正在编写代码来创建对象、克隆对象,然后比较两者。 所讨论的对象 Octagon 是对象 GeometricObject 的扩展 public class Octagon extends Geomet
我看到clone()在django代码中被广泛使用 queryset.query.clone() queryset.clone() 它的用途是什么?我应该模仿查询集或管理器方法中的行为吗? 最佳答案
我尝试导入 git project进入 eclipse 。手册告诉我在控制台中使用此命令: git clone http://git-wip-us.apache.org/repos/asf/mina-
我正在使用 jquery .clone(),它工作正常。但是我的问题是,当我克隆我的输入字段时,它也会克隆前一个字段的值。我不想克隆该值。我该如何克服这个问题? 这是我的代码 function add
在 this SO thread 中,结果表明,在制作项目副本方面,切片比任何方法都快。 使用: list1 = ['foo','bar'] copy1 = list1 * 1 list1.pop()
我有一个自动脚本可以解析服务器并克隆其中一个文件夹中的所有存储库。它所做的伪代码是: for each repo_name if a folder named like repo_name exi
我是一名优秀的程序员,十分优秀!