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中对 ...
随机推荐
- Java 语言基础之数组(一)
数组定义及格式: 数组: 同一种类型数据的集合, 就是一个容器 定义数组格式1: 元素类型[] 数组名 = new 元素类型[元素个数(即数组长度)]; 说明: 数组是一个容器.而容器属于一个实体,实 ...
- Learning How to Learn学习笔记(转)
add by zhj: 工作中提高自己水平的最重要的一点是——快速的学习能力.这篇文章就是探讨这个问题的,掌握了快速学习能力的规律,你自然就有了快速学习能力了. 原文:Learning How to ...
- django自带过滤器大全
1.可以通过过滤器来修改变量的显示,过滤器的形式是:{{ variable | filter }},管道符号'|'代表使用过滤器 2.过滤器能够采用链式的方式使用,例如:{{ text | escap ...
- Android 实现瀑布流的两种思路
瀑布流怎么样我就不多介绍了.下面说说我想到的两个方法. 方法一,控件的叠加: ScrollView+LinearLayout.在ScrollView里面加一个水平方向的LinearLayout,在水平 ...
- ubuntu下安装qwt
转载自:http://blog.chinaunix.net/uid-20717410-id-256767.html 相对于官方说明,特别适应于使用qt IDE开发者. //以下为引用: 虽然官网上说只 ...
- Elasticsearch中文搜索环境搭建
Elasticsearch是一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎,功能强大,最近刚好要研究搜索这一块,简要记录备日后查阅 安装Java JDK,由于Lucene是用J ...
- boost noncopyable类
1. 当声明一个类时,编译器会自动为该类生成默认构造函数,复制构造函数,赋值操作符以及析构函数: 2.自动生成的各个函数和操作符都是public的: 3.当声明一个类不允许复制时,可以将一个类的复制构 ...
- Authentication Overview
Authentication Overview Service accounts User accounts API keys
- go——字典
Go中字典类型是散列表(hash table)的一个实现,其官方称谓是map.散列表是一个实现了关联数组的数据结构,关联数组是用于表示键值对的无序集合的一种抽象数据类型.Go中称键值对为键-元素对,它 ...
- Cpython-并发编程
阅读目录 一 背景知识 二 python并发编程之多进程 三 python并发编程之多线程 四 python并发编程之协程 五 python并发编程之IO模型 六 补充:paramiko模块 七 作业 ...