java对象的深浅clone
在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。
浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制,下面将对两者进行详细介绍。
浅clone:
在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
示意如下图:

Object类中的native clone方法提供了浅clone的支持。可以实现Cloneable接口并调用Object的clone方法为一个类实现浅clone:
public static void main(String[] args) throws CloneNotSupportedException {
Foo f1 = new Foo(1, new Bar(0));
Foo f2 = f1.clone();
System.out.println(f1);
System.out.println(f2);
f1.id = 2;
f1.bar.setId(2);
System.out.println(f1);
System.out.println(f2);
}
public static class Foo implements Cloneable {
private int id;
private Bar bar;
public Foo(int id, Bar bar) {
this.id = id;
this.bar = bar;
}
@Override
public Foo clone() throws CloneNotSupportedException {
return (Foo) super.clone();
}
@Override
public String toString() {
return "Foo{" +
"id=" + id +
", bar=" + bar +
'}';
}
}
public static class Bar implements Cloneable {
private int id;
public Bar(int id) {
this.id = id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Bar{" +
"id=" + id +
'}';
}
}
程序的执行结果如下:
Foo{id=1, bar=Bar{id=0}}
Foo{id=1, bar=Bar{id=0}}
Foo{id=2, bar=Bar{id=2}}
Foo{id=1, bar=Bar{id=2}}
在示例程序中改变了f1的引用变量成员bar的值,f2的成员变量bar也受到了影响。不过改变了f1的直接类型成员id的值,f2却没有受影响。
可知:浅clone只能clone成员变量中直接类型的值,对于应用类型的值则是clone了引用对象的地址。
深clone:
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。
简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
示意如下图:

要让我们上面的程序支持深clone,需要对其做些调整:
首先需要给Bar类也添加clone方法的支持:
public static class Bar implements Cloneable {
private int id;
public Bar(int id) {
this.id = id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Bar{" +
"id=" + id +
'}';
}
@Override
public Bar clone() throws CloneNotSupportedException {
return (Bar) super.clone();
}
}
而后修改Foo类的clone方法:
@Override
public Foo clone() throws CloneNotSupportedException {
Foo f = (Foo) super.clone();
f.bar = bar.clone();
return f;
}
执行结果如下:
Foo{id=1, bar=Bar{id=0}}
Foo{id=1, bar=Bar{id=0}}
Foo{id=2, bar=Bar{id=2}}
Foo{id=1, bar=Bar{id=0}}
此时f2不再受到f1的影响了。
此时再继续想一下,如果Bar中还有引用类型成员呢,如果Bar中的引用类型成员也有自己的引用类型成员,那么该怎么办呢?
挺好解决的事情,懒得解释了。
java对象的深浅clone的更多相关文章
- Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨
Java对象克隆(Clone)及Cloneable接口.Serializable接口的深入探讨 Part I 没啥好说的,直接开始Part II吧. Part II 谈到了对象的克隆,就不得不说为什么 ...
- (转)Java对象克隆(Clone)及Cloneable接口、Serializable接口的深入探讨
原文地址:http://blog.csdn.net/kenthong/article/details/5758884 Part I 没啥好说的,直接开始Part II吧. Part II 谈到了对象的 ...
- 关于Java的Object.clone()方法与对象的深浅拷贝
文章同步更新在个人博客:关于Java的Object.clone()方法与对象的深浅拷贝 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Object.clon ...
- java对象转json应clone,避免生成json串有问题
今天因为一个java对象转json,搞了我一下午,在些记录一下: 是这样:我在strtuts2的action中调用services返回 Row: 26, 中国银行海鹰, 29, 东楼, 36, 1F ...
- Object.clone()方法与对象的深浅拷贝
转载:[https://www.cnblogs.com/nickhan/p/8569329.html] 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Obj ...
- Java对象的克隆和深浅问题
Java实现克隆的方式 Java实现克隆的方式有如下两种, 推荐采用实现Cloneable接口的方式 实现Cloneable接口, 重写clone方法, 调用父类的clone方法 还有另一种方法, 不 ...
- java对象clone
java克隆 为什么需要克隆 我们在很多时候需要使用一个对象去记录另外一个对象的当前状态,对象中可能会有很多属性,如果我们一个一个去设置,不仅不方便,而且效率很低,我们看一个初学者可能遇到的问题 cl ...
- java对象比较器和克隆
一.比较器Comparable和Comparator 上一篇博客介绍了工具类Arrays工具类 .我们可以对基本类型的数组调用Arrays.sort()函数来进行数组的排序.排序操作在日常开发中经常要 ...
- JAVA 对象拷贝
1.java里的clone分为: A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍. Java中对 ...
随机推荐
- 【IDEA】安装Jrebel插件:JRebel6.4.3+破解补丁
Jrebel 通过社交分享得到的激活码不能用了.在网上找了一波,发现通过反向代理破解最好,但激活过程中报错 Check your network connection and/or VPN setti ...
- Apache-ActiveMQ transport XmlMessage
前言 本文原创,转载请说明出处! Apache-ActiveMQ:是Apache提供的一款开源的消息传送服务,不论是安装还是使用都非常简单实用,可以作为消息缓存管理器来使用(个人观点),看看Activ ...
- Phonetic Symbols:2个半元音:[w] ,[j]
2个半元音音标发音技巧与单词举例 原文地址:http://www.hlyy.in/1243.html 2个半元音音标发音技巧与半元音单词举例 [w] 发音技巧: 嘴唇张开到刚好可以含住一根吸管的程度 ...
- Create a Group Policy Central Store
一.How to create a Group Policy Central Store You have downloaded or created your own Group Policy Ad ...
- 并发测试 java.lang.OutOfMemoryError: GC overhead limit exceeded Xms Xmx 阻塞请求 单节点 请求分发 负载均衡
at javax.servlet.http.HttpServlet.service(HttpServlet.java:705) at javax.servlet.http.HttpServlet.se ...
- In-Stream Big Data Processing
http://highlyscalable.wordpress.com/2013/08/20/in-stream-big-data-processing/ Overview In recent y ...
- jQuery实现图片预览
摘自:http://www.cnblogs.com/leejersey/p/3660202.html JS代码: /* *名称:图片上传本地预览插件 v1.1 *作者:周祥 *时间:2013年11月2 ...
- Python爬虫之-Requests
Requests模块 Python标准库中提供了:urllib.urllib2.httplib等模块以供Http请求,但是,它的 API 太渣了. 它是为另一个时代.另一个互联网所创建的.它需要巨量的 ...
- Java I/O(一) NIO概述
基本概念 BIO:是堵塞I/O,无论是磁盘I/O,还是网络I/O,数据在写入OutputStream和InputStream都可能发生堵塞,一旦有堵塞,线程会失去CPU的使用权(堵塞). NIO:简单 ...
- mysql密码忘记该怎么办?
环境:linux;mysql5.7 mysql密码忘记: [root@izwz9f40l0qo5cpnn8qwmpz ~]# mysql -u root -pEnter password: ERROR ...