1、实现Cloneable接口表明该类的对象是允许克隆的。

2、允许克隆的意思是:可以调用clone()方法。

3、深拷贝还是浅拷贝,取决于如何重写Object的clone()方法。

4、原对象和克隆对象的关系:

深拷贝:阳关道和独木桥;

浅拷贝:藕断丝连。

上面的第二点解释一下,如果没有实现Cloneable就调用clone()方法,会抛出异常。看下Object源码就知道了:

 protected Object clone() throws CloneNotSupportedException {
if (!(this instanceof Cloneable)) {//这里会检查是否是Cloneable的实例
throw new CloneNotSupportedException(
"Class " + getClass().getName() +" doesn't implement Cloneable");
} return internalClone();
}

下面举一个深拷贝的例子:

ArrayList的clone()方法:

  //深拷贝
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
//新开辟一个内存空间给ArrayList的对象成员Object[] elementData;
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
//transient Object[] elementData;

这样得到新的ArrayList对象,则是一个完全独立的对象,包括对象属性成员和原来对象没有任何联系。你走你的阳关道,我走我的独木桥,你以后做什么事都影响不了我。这就是深拷贝。

如果把上面的深拷贝改成浅拷贝,将会变成:

  //浅拷贝
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
//有公用的对象成员elementData,它就是连接两个对象的罪魁祸首。
v.elementData = elementData;
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
//transient Object[] elementData;

使用上面这个浅拷贝的clone()方法,原对象和克隆对象各自的对象成员elementData指向同一块内存地址,藕断丝连,相互影响着。你受伤了,我就难过;你过的开心,我就默默祝福你;你想我的时候,我也在想你。这就是浅拷贝。

补充:如果A的对象成员属性是自己定义的类型(记为B),A想要深拷贝,需要依靠B的深拷贝clone()方法。

参考书籍:Effective Java(第2版)

java开发——Cloneable接口、clone()方法和深浅拷贝的更多相关文章

  1. Java的Cloneable接口还有深浅复制

    我的小记录 首先语法上,搞清除,Java有个Cloneable接口,但这个接口是没有定义方法的. 那实现了这个接口有什么用呢? 再看Object类中,有个clone()方法,这个方法提供一个浅复制的功 ...

  2. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  3. jQuery开发插件的两个方法 js 深浅拷贝

    1.jQuery.extend(object);为扩展jQuery类本身.为类添加新的方法.由全局函数来调用, 主要是用来拓展个全局函数 2.jQuery.fn.extend(object);为jQu ...

  4. java Object对象的clone方法

    参考copy链接:http://blog.csdn.net/bigconvience/article/details/25025561 在看原型模式,发现要用到clone这个方法,以前和朋友聊过,没怎 ...

  5. Java 中如何使用clone()方法克隆对象?

    java为什么要 对象克隆: 在程序开发时,有时可能会遇到以下情况:已经存在一个对象A,现在需要一个与A对象完全相同的B 对象,并对B 对象的属性值进行修改,但是A 对象原有的属性值不能改变.这时,如 ...

  6. 没想到吧,Java开发 API接口可以不用写 Controller了

    本文案例收录在 https://github.com/chengxy-nds/Springboot-Notebook 大家好,我是小富~ 今天介绍我正在用的一款高效敏捷开发工具magic-api,顺便 ...

  7. java中获取接口(方法)中的参数名字(eclipse设置编译参数)(java8 javac -parameters)

    interface接口参数 jdk1.7及以前使用spring功能实现的: 注意: 1.该功能只能获取类的方法的参数名,不能获取接口的方法的参数名. public static void test() ...

  8. java开发之——[接口回调]

    一.回调的含义和用途 1. 什么是回调? 一般来说,模块之间都存在一定的调用关系,从调用方式上看,可以分为三类:同步调用.异步调用和回调.同步调用是一种阻塞式调用,即在函数A的函数体里通过书写函数B的 ...

  9. 在idea的java开发中字符串length()方法获取长度与赋值不符的问题

    最近在开发中用到length()方法获取中文字符串的长度,发现获得的长度与实际不符.比如个String类型赋值为"中",但获取长度却是2. 这让我百思不得其解,后来突然想起来我在研 ...

随机推荐

  1. F5 BIG-IPLTM串联组网连接模式

  2. [LC] 55. Jump Game

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  3. basecalling|vector mark|Assembly的难题|

    生物信息学 染色体可以据染色图谱判断染色体号码,1-22号染色体依次变短,它们影响机体发育,23号染色体决定性别.肿瘤是由于遗传密码变异造成的.因此,遗传密码的解读非常重要,但是因为遗传密码长度非常长 ...

  4. svn merge Property conflicts

    svn merge代码的时候,出现Property conflicts的解决方案.可以参考:http://stackoverflow.com/questions/23677286/conflict-w ...

  5. 吴裕雄--天生自然 人工智能机器学习实战代码:ELASTICNET回归

    import numpy as np import matplotlib.pyplot as plt from matplotlib import cm from mpl_toolkits.mplot ...

  6. 吴裕雄--天生自然KITTEN编程:移动与旋转

  7. xampp安装后启动apache出现端口占用问题

    apache默认监听电脑80端口,当端口被占用时,xampp无法正常启动apache.我们需要将端口解除占用再启动. xampp报错: Problem detected!19:36:24 [Apach ...

  8. iOS开发之多线程(NSThread、NSOperation、GCD)

    整理一些多线程相关的知识. 并行 & 并发 1.并行:并行是相对于多核而言的,几个任务同时执行.2.并发:并发是相对于单核而言的,几个任务之间快速切换运行,看起来像是"同时" ...

  9. 一个异步访问redis的内存问题

    | 分类 redis  | 遇到一个redis实例突然内存飙高的案例, 具体症状如下: 客户端使用异步访问模式 单个请求的回包很大,hgetall一个8M的key 由于访问量比较大,已经登录不上red ...

  10. Js对于数组去重提高效率一些心得

    最近在找工作,好几次面试都问过数组去重的问题.虽然问的都不一样,但是核心思想是没有变的. 第一种是比较常规的方法 思路: 构建一个新的数组存放结果 for循环中每次从原数组中取出一个元素,用这个元素循 ...