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. 57)PHP,自动加载类注意项

    关于这个里面的那个if  里面判断是否是核心启动类,一般会想到,用in_array或者是isset              in_array判断是数组里面有没有这个值,但是isset判断的是数组里面 ...

  2. es6变量和函数的提升、暂时性死区?

    es6变量和函数的提升.暂时性死区?

  3. python3下scrapy爬虫(第六卷:利用cookie模拟登陆抓取个人中心页面)

    之前我们爬取的都是那些无需登录就要可以使用的网站但是当我们想爬取自己或他人的个人中心时就需要做登录,一般进入登录页面有两种 ,一个是独立页面登陆,另一个是弹窗,我们先不管验证码登陆的问题 ,现在试一下 ...

  4. 听《Sara》

    Sara这首歌太好听了,虽然没有清楚具体是唱什么,但我感觉是讲一个故事,很好奇,我找到了歌词. Sara 塞拉 鲍勃迪伦 I laid on a dune, I looked at the sky, ...

  5. Java IO: 异常处理

    原文链接 作者:Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 流与Reader和Writer在结束使用的时候,需要正确地关闭它们.通过调用close()方法 ...

  6. 2015-09-14-C++基础

    声明与定义 声音与定义的区别在于,声明没有给变量分配空间,而定义则给变量分配了空间:定义也是声明. extern int i; // 声明但未定义 int i ; //声明且定义 extern dou ...

  7. kendoUI 免费部分开发部分经验。

    kendo分多个版本,核心UI免费版.NET,JAVA,PHP对应的前后端开发版. 基础免费版开放的UI经多个测试,与收费封装的UI并无区别,收费版提供了后端代码和前端封装语法,使不懂JS前端的也可简 ...

  8. Nginx笔记总结二十:nginx索引目录配置

    location / { autoindex on; autoindex_localtime on; }

  9. python ATM项目

    1.需求: 指定最大透支额度 可取款 定期还款(每月指定日期还款,如15号) 可存款 定期出账单 支持多用户登陆,用户间转帐 支持多用户 管理员可添加账户.指定用户额度.冻结用户等 购物车: 商品信息 ...

  10. let和const区别

    let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. const命令 const声明一个只读的常量.一旦声明,常量的值就不能改变.