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. UVALIVE 4556 The Next Permutation

    4556 The Next PermutationFor this problem, you will write a program that takes a (possibly long) str ...

  2. Linux实战教学笔记38:企业级Nginx Web服务优化实战(下)

    四,Nginx站点目录及文件URL访问控制 4.1 根据扩展名限制程序和文件访问 Web2.0时代,绝大多数网站都是以用户为中心多的,例如:bbs,blog,sns产品,这几个产品都有一个共同特点,就 ...

  3. haproxy 配置 说明

    一.环境说明实验环境OS CentOS5.4192.168.0.14    proxy192.168.0.24    web1192.168.0.64    web2 官方地址:http://hapr ...

  4. 61. Rotate List(List)

    Given a list, rotate the list to the right by k places, where k is non-negative. For example: Given ...

  5. 我为什么使用Kubuntu

    网上看贴,包括身边的同事.朋友,总会问的问题是:我该选择哪个Linux发行版?使用久了,就会觉得这个问题其实不是问题,纯属个人习惯而已,当你真正习惯.理解了Linux,那么任何一个发行版的优点,你都有 ...

  6. Echarts主题颜色

    Echarts主题颜色搜集: 直接覆盖默认颜色即可 例如在 echarts.setOption({ '#2ec7c9','#b6a2de','#5ab1ef','#ffb980','#d87a80', ...

  7. 设计模式--适配器模式(Adapter)详解

    适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题.主要分为三类:类的适配器模式.对象的适配器模式.接口的适配器模式. 01.类的适配器模式 核心 ...

  8. Python监控日志程序-乾颐堂

    一个简易的日志监控的脚本,功能如下:1.windows环境2.当匹配日志关键字时会发出声音,匹配的关键字不同,播放的声音不同3.能做到实时响应 注意:是在win环境下哦 直接上代码吧 1 2 3 4 ...

  9. ajax 整个表单的提交

    重点:data: $("#form1").serialize() function setSaveNext() { setSaveData(); var cx = pageInde ...

  10. win10 startup启动目录路径命令

    仅对当前用户生效: C:\Users\Username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 开始-运行 shel ...