Summary

浅克隆与深克隆对于JavaSE来说,是个难度系数比较低的概念,但不应该轻视它。

假设一个场景:对于某个list,代码里并没有任何对其的直接操作,但里面的元素的属性却被改变了,这可能就涉及到这个概念。

Description

浅克隆指仅copy对象位于栈内存中的引用(reference)。copy后,新旧两个引用指向同一个堆内存对象(即同一内存区域),但是堆内存中实际的对象copy前后均只有一个。使用"==" operator比较二者的地址会返回true。(不同引用,同一对象)

深克隆指则会copy一个新的对象并返回相应引用,即开辟了新的堆内存空间,因此使用“==” operator来比较两者的地址时会返回false。(不同引用,不同对象)

浅克隆(shallow clone)

  1. clone对象是实例对象时,使用“=”操作符进行浅克隆。
  2. clone对象是对象数组的元素时,使用 System.arraycoppy() 进行浅克隆。(你非得要用"=" foreach地clone也没人拦着)

jdk中显式定义的clone操作基本上都使用:

 System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

例如ArrayList中的clone()、Arrays.copyOf()等对具体数组的clone其实底层都是调用该方法。

 package com.scv.test.clone;

 public class ShallowCloneTest {

     public static void main(String[] args) throws Exception {
Zerg z0 = new Zerg();
Zerg z1 = z0;
System.out.println("0. " + (z0 == z1));//"="操作符用于对象的浅克隆 Zerg[] array0 = new Zerg[]{new Zerg(), new Zerg()};
Zerg[] array1 = new Zerg[array0.length];
System.arraycopy(array0, 0, array1, 0, array0.length);//System.arraycopy()用于数组的浅克隆
System.out.println("1. " + (array0 == array1));
for(int i = 0; i < array0.length; i++){
System.out.println("Comparing element of array:" + (array0[i] == array1[i]));
}
} } class Zerg{ } /* Output:
0. true
1. false
Comparing element of array:true
Comparing element of array:true
*/

验证Shallow Clone

深克隆(deep clone)

jdk中并没有显式定义深克隆,或者说并没有直接提供工具类来进行。要让你的自定义类支持深克隆,必须具备两个条件:

  1. implements Cloneable interface.
  2. override clone() defined in java.lang.Object.

如果不实现Cloneable而直接override Object的clone(),则会抛出CloneNotSupportedException。

 package com.scv.test.clone;

 public class DeepCloneTest {

     public static void main(String[] args) throws Exception {
CloneableZerg z0 = new CloneableZerg();
CloneableZerg z1 = z0.clone(); System.out.println("0. " + (z0 == z1));
} } class CloneableZerg implements Cloneable{ @Override
public CloneableZerg clone() throws CloneNotSupportedException{
return (CloneableZerg)super.clone();
}
} /* Output:
0. false
*/

验证Deep Clone

实际上,你可以自定义哪些成员变量(field)允许clone,哪些不允许(有点transient的感觉?)。

jdk中的实现:ArrayList中的浅克隆与深克隆

 package com.scv.test.clone;

 import java.util.ArrayList;

 public class ArrayListCloneTest {

     public static void main(String[] args) throws Exception {
CloneTarget t = new CloneTarget(); ArrayList<CloneTarget> list0 = new ArrayList<CloneTarget>(1);
list0.add(t);
ArrayList<CloneTarget> list1 = (ArrayList<CloneTarget>) list0.clone();
list0.get(0).setFieldA(20); System.out.println("0. " + (list0 == list1));
System.out.println("1. " + (list0.get(0) == list1.get(0)));
System.out.println("2. " + list1.get(0).getFieldA());
} } class CloneTarget implements Cloneable{ private int fieldA = 10; @Override
public CloneTarget clone() throws CloneNotSupportedException{
return (CloneTarget)super.clone();
} public void setFieldA(int a){
fieldA = a;
} public int getFieldA(){
return fieldA;
}
} /*
* Output:
* 0. false
* 1. true
* 2. 20
*/

Click Me

操作说明:

  1. 创建一个ArrayList对象list0
  2. list0中加入一个对象t
  3. 克隆list0对象为list1
  4. 再修改list0中元素(即t)的属性

结果说明:

  1. ArrayList实现了Cloneable接口,arraylist.clone()为深克隆,故list0与list1分别指向不同内存区域。
  2. ArrayList对象的clone()对于内部数组的元素仅为浅克隆,故list0中的元素(t)与list1中的元素为同一个,对list0元素的修改将影响到list1的元素。

Java:浅克隆(shallow clone)与深克隆(deep clone)的更多相关文章

  1. java 浅克隆(浅复制)和深克隆(深复制)

    http://www.voidcn.com/blog/u011380813/article/p-6161450.html https://gold.xitu.io/entry/570d89651ea4 ...

  2. Deep Clone 常用方式总结

    Deep Clone Example 总结 Deep Clone 一般有如下几种实现方式: 纯手工每个类实现赋值 (ps: 不做介绍,一般都不想这么玩) 序列化和反序列化 纯反射 emit 或 Exp ...

  3. 深拷贝(deep clone)与浅拷贝(shallow clone)

    深拷贝(deep clone)与浅拷贝(shallow clone) 浅复制(浅克隆):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复 ...

  4. java 浅克隆 深克隆

    对象的克隆是java的一项高级技术,他可以根据给定的对象,获得与其完全相同的另一个对象. 1.浅克隆主要是复制对象的值 2.深克隆:当类存在聚合关系的时候,克隆就必须考虑聚合对象的克隆,可以复制引用类 ...

  5. java浅克隆和深克隆,序列化和反序列化实现深克隆(封装序列化和反序列化操作)

    本篇博客内容: 一.浅克隆(ShallowClone)和深克隆(DeepClone) 二.序列化和反序列化实现深克隆 三.封装序列化和反序列化操作 ObjectOutputStream + 内存流By ...

  6. Ruby中如何复制对象 (deep clone)(转载)

    Ruby中如何复制对象 (deep clone) 用Ruby复制一个对象(object)也许没有你想像的那么容易. 今天我google了半天, 做个总结吧. 先从最简单的开始, b = a 是复制吗? ...

  7. JavaScript 中的对象深度复制(Object Deep Clone)

    JavaScript中并没有直接提供对象复制(Object Clone)的方法. JavaScript中的赋值,其实并不是复制对象,而是类似`c/c++`中的引用(或指针),因此下面的代码中改变对象b ...

  8. java中的Object类和其clone()

    1.Object是所有类的父类,任何类都默认继承Object,即直接或间接的继承java.lang.Object类.由于所有的类都继承在Object类,因此省略了extends Object关键字. ...

  9. What is the most efficient way to deep clone an object in JavaScript?

    What is the most efficient way to deep clone an object in JavaScript? Reliable cloning using a libra ...

随机推荐

  1. LCS最长共同子序列

    2017-09-02 15:06:57 writer:pprp 状态表示: f(n,m)表示s1[0..n]和s2[0..m]从0开始计数,最终结果是f(N-1,M-1)考虑四种情况: 1/ s1[n ...

  2. UVa 11768 格点判定(扩展欧几里得求线段整点)

    https://vjudge.net/problem/UVA-11768 题意: 给定两个点A(x1,y1)和B(x2,y2),均为0.1的整数倍.统计选段AB穿过多少个整点. 思路: 做了这道题之后 ...

  3. UVa 10883 超级平均数(二项式系数+对数计算)

    https://vjudge.net/problem/UVA-10883 题意: 给出n个数,每相邻两个数求平均数,依次类推,最后得到1个数,求该数. 思路: 演算一下可以发现最后各个数的系数就是二项 ...

  4. Unique Binary Search Trees,Unique Binary Search Trees2 生成二叉排序树

    Unique Binary Search Trees:求生成二叉排序树的个数. Given n, how many structurally unique BST's (binary search t ...

  5. codeforces103E Buying Sets

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  6. 聚类算法——MCL

    最近在看聚类方面的论文,接触到了MCL聚类,在网上找了许久,没什么中文的资料,可能写的最具体的便是GatsbyNewton写的 马尔可夫聚类算法(MCL) 这篇博客了.但是,其中仍有一些不详细的地方. ...

  7. PHP函数前面添加@的作用

    @是PHP提供的错误信息屏蔽的专用符号. 比如在一个函数前使用@ @mysql_query 不会出现Warning, 而原来mysql_query 在遇到错误时会在页面上访提示Warning. @是可 ...

  8. 异步提交表单插件jquery.form.min.js的使用实例

    因为项目中需要达到效果:前台点击按钮弹出文件选择框,选择文件确定之后,上传到后台对文件进行处理并给出响应信息. 尝试过使用$.post,$.ajsx,将表单序列化之后传到后台,但是后台并不能收到文件, ...

  9. python异常列表

    http://www.runoob.com/python/python-exceptions.html https://www.cnblogs.com/zhangyingai/p/7097920.ht ...

  10. 【Demo】jQuery 可编辑表格

    功能实现: (1)设定单元格的单击事件,判定被单击单元格是否已经是可编辑状态: (2)取出单元格原有内容,想单元格中加入文本框,并把原有内容显示在文本框中: (3)当用户编辑完成或者取消编辑后,将文本 ...