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. MyBatis3 用log4j在控制台输出 SQL

    用log4j在控制台输出 SQL 在spring-mybatis.xml中配置 <bean id="sqlSessionFactory" class="org.my ...

  2. 使用NPM在项目中引入【lodash】

    mkdir [文件名 ] 创建项目文件 mkdir lodashDemo cd [文件名] 进入项目文件 cd lodashDemo nvm -v 查看nvm版本,确定nvm已安装 nvm -v No ...

  3. Swiper thymeleaf

    html页面: <div class="swiper-container swiper_tjzt"> <div class="swiper-wrappe ...

  4. qt的exe文件查找依赖的dll

    用qtcreater编译完工程生成的exe文件往往会依赖dll文件.如何一次定位exe文件所以依赖的所有dll文件呢,今天发现了软件叫hap-depends. 截图如下: 用这个软件打开exe文件就会 ...

  5. EXADATA智能扫描

    提要:查询特定的要求:智能扫描只可用于完整的表或索引扫描.智能扫描只能用于直接路径读取: 直接路径读取会自动用于并行查询. 直接路径读取可以用于串行查询.默认情况下不使用它们进行小型表的串行扫描.使用 ...

  6. Shiro 集成Spring 使用 redis时 使用redisTemplate替代jedisPool(五)

    1.添加依赖架包: <dependency> <groupId>org.springframework.data</groupId> <artifactId& ...

  7. Java中String类型详解

    这篇博客是我一直想总结的,这两天一直比较忙,先上传下照片吧,过后有时间再弄成正常的. 本文主要是对Java中String类型的总结,包括其在JVM中是怎么存储的...

  8. 使用dataview组件显示服务器端xml文件数据

    来自<sencha touch权威指南>,约193页开始 ------------------------------------- (1)app.js代码: Ext.require([' ...

  9. strlen头文件

    #include <string.h> 函数strlen strsep 等等

  10. c#反射优化 表达式树

    using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; us ...