Cloning 分两类:影子克隆 shallow cloning

        深度克隆 deep cloning

* 调用 clone() 需要 implments Cloneable。此函数为 protected,如果在外部调用,需要把它重写为 public 的。Cloneable 接口本身其实是空的,也就是没有方法需要实现。所以 clone() 可以不重写。这种空的接口被称为 marker interface 标记接口 或 tagged interface 标签接口。

1. 影子克隆是简单的克隆,对于一个对象,克隆后的对象和被克隆的对象可能有相同的属性的引用。

比如:

public class Date {

    private int year;
private int month;
private int day; public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
} ************************************** public class Employee { private String name;
private int age;
private Date hireDate; public Employee (String name, int age, Date hireDate){
this.name = name;
this.age = age;
this.hireDate = hireDate;
} public static void main () {
Employee e1 = new Employee ("Jack", 32, new Date (13,2,30));
Employee e2 = (Employee) e1.clone();
}
}

这种情况下:

  • e1 == e2 为 false
  • e1.name == e2.name 为 true
  • e1.hireDate == e2.hireDate 为 true

* 所以,e1和e2虽然是不同的引用,但他们的属性 name 和 hireDate 却是同一个引用。

当修改e2时,

  • e2.age 的修改不影响 e1.age
  • e2.name 的修改不影响 e1.name ,因为 String 是 final 类,是不可变的,e2.name 的修改自动为其创建了一个新的 String。
  • e2.hireDate 的修改会影响 e1.hireDate (ex. e2.hireDate.setYear(10)),执行完此语句后,e1.hireDate 的 year 变成了 10。

这可能是我们不想看到的,对克隆的修改不应该影响本体的值。

这种情况就应该使用 深度克隆。

2. 深度克隆

深度克隆实际上就是在类中重写 clone(),使得以上的问题得以避免。

实现方法比如:

@Override
protected Object clone() throws CloneNotSupportedException {
Employee emp = (Employee) super.clone();
if (hireDate != null) // no point cloning a null object (one that does not exist)
emp.hireDate = new Date(hireDate.year, hireDate.month, hireDate.day);
return emp;
}

新建的 Date 让 e1 和 e2 的 hireDate 区分开来,互不影响了。

所以当我们想用 clone() 函数时,如果类中包含的属性有其他类的类型,一定要重写 clone()。

《Beginning Java 7》 - 2 - Cloning 克隆的更多相关文章

  1. Java提高篇——对象克隆(复制)

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  2. Java List的深度克隆

    关于java List的深度克隆 List是java容器中最常用的顺序存储数据结构之一.有些时候我们将一组数据取出放到一个List对象中,但是可能会很多处程序要读取他或者是修改他.尤其是并发处理的话, ...

  3. Java基础--对象的克隆

    文章转载自https://www.cnblogs.com/Qian123/p/5710533.html 阅读目录 为什么要克隆? 如何实现克隆 浅克隆和深克隆 解决多层克隆问题 总结 假如说你想复制一 ...

  4. java中的深浅克隆

    假设有一个对象object,在某处又需要一个跟object一样的实例object2,强调的是object和object2是两个独立的实例,只是在开始的时候,他们是具有相同状态的(属性字段的值都相同). ...

  5. java对象比较器和克隆

    一.比较器Comparable和Comparator 上一篇博客介绍了工具类Arrays工具类 .我们可以对基本类型的数组调用Arrays.sort()函数来进行数组的排序.排序操作在日常开发中经常要 ...

  6. Java学习笔记--对象克隆

    转自:Edward_qing_Lee 的专栏 http://blog.csdn.net/edward_qing_lee/article/details/8249102 一.java 方法参数 理解: ...

  7. Java 原型模式(克隆模式)

      Java 的设计模式有 23 种,前段时间小编已经介绍了单例模式,由于我们在学习 Spring 的时候在 bean 标签的学习中碰到了今天要讲的原型模式,那么小编就已本文来介绍下原型模式. 原型模 ...

  8. JAVA中对象的克隆及深拷贝和浅拷贝

    使用场景: 在日常的编程过程 中,经常会遇到,有一个对象OA,在某一时间点OA中已经包含了一些有效值 ,此时可能会需一个和OA完全相对的新对象OB,并且要在后面的操作中对OB的任何改动都不会影响到OA ...

  9. 深入浅出Java中的clone克隆方法,写得太棒了!

    作者:张纪刚 blog.csdn.net/zhangjg_blog/article/details/18369201/ Java中对象的创建 clone 顾名思义就是 复制 , 在Java语言中, c ...

随机推荐

  1. IDEA快捷键【收藏】

    Ctrl+Alt+L 格式化代码Ctrl+Shift+J 两行合成一行,删去不必要的空格匹配代码格式其他快捷键:[常规]Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 ...

  2. Elasticsearch前沿:ES 5.x改进详解与ES6展望

    转:http://www.dataguru.cn/article-11094-1.html 曾勇(Medcl),Elastic 工程师与布道师,2015 年加入 Elastic 公司.加入 Elast ...

  3. 代码质量检测-Sonar

    一. Sonar简介 sonarqube系统是一个代码质量检测工具 由以下四个组件组成(https://docs.sonarqube.org/display/SONAR/Architecture+an ...

  4. CloudStack + KVM + HA

    KVM高可用性CS4.2暂时没有实现 The Linux Kernel Virtual Machine (KVM) is a very popular hypervisor choice amongs ...

  5. Python学习笔记_读Excel去重

    读取一个Excel文件,按照某列关键字,如果有重复则去掉 这里不介绍所有的解决办法,只是列出一个办法. 软件环境: OS:Win10 64位 Python 3.7 测试路径:D:\Work\Pytho ...

  6. chrome crx下载路径

    chrome crx下载后会被删除,可在检查时粘贴出来,下载路径在: %localappdata%\Google\Chrome\User Data\Webstore Downloads 参考:http ...

  7. docker镜像存出与载入

    尝试从官网上下载ubuntu镜像,太慢下载不下来. 使用daocloud加速器进行加速之后,由于公司网络不好,仍然下载不下来. 没办法,只能从别的环境上搞一个已经存在的ubuntu镜像,折腾到自己的虚 ...

  8. Node.js基本使用(超基础)

    Node.js是什么 Node.js是一个能够在服务器端运行JavaScript的开放源代码.跨平台JavaScript运行环境 Node采用Google开发的V8引擎运行js代码,使用事件驱动.非阻 ...

  9. functions函数插件的定义和使用

    创建Smarty插件:在插件目录(plugins)里新建文件 类型.插件名.php文件,然后插件方法名字书写规范: smarty_类型_插件名([...]){}在模板(tpl文件)中调用插件时格式{插 ...

  10. mysql 添加字段,修改字段的用法

    1.添加字段 ALTER TABLE 表明 add 字段名称 类型(int,char,VARCHAR...) DEFAULT 默认值  位置(FIRST, AFTER+字段名称); 2.删除 ALTE ...