一个类要想实现克隆,需要实现Cloneable接口,表明这个类的对象具有克隆的功能。

Cloneable接口是一个mixin接口,它里面并没有任何的抽象方法,类似的接口有Serializable接口,表明该类的对象可以序列化。

首先应该明确通过一个对象克隆出另一个对象的概念:通过一个对象克隆出另一个对象,简称对象1和对象2,这两个对象就成为两个独立的对象,

那么对对象1做任何的修改,对象2应该不受影响;对对象2做任何的修改的,对象1就不应该受影响。这样就要求对象1与对象2的实例域各自是独立的。

那么我们知道一个对象的实例域,包括基本类型(int,long..等等)的域,引用类型的域(分为可变的域和final不可变的域)。

现在了解Object类的clone()方法:

protected native Object clone() throws CloneNotSupportedException;

clone()方法是一个受保护的本地方法。

clone()方法的通用约束如下:

x.clone() != x        应该返回true

x.clone().getClass() == x.getClass()        应该返回true

x.clone().equals(x)           应该返回true

对于实现了Cloneable()接口的类,也就是具有克隆能力的类,我们总是期望它提供一个功能适当的公有的clone()方法。

如果我们在一个类的clone()方法只调用super.clone(),然后返回,它仅仅是返回了一个新的对象,这个对象具有和原对象一样的基本类型域,

但是这个对象的引用类型域引用的对象还是原对象的引用类型域所引用的对象。这样就导致一个问题,对原对象引用类型的域所做的修改会影响

到新对象的引用类型域。     也就是说调用Object类的克隆方法,仅仅完成了新对象的创建,和基本类型域的克隆,但是引用类型域的引用还是

指向了旧对象的引用类型域的实例。如下图:

但是有一种情况允许出现这样的克隆,这个类引用类型域只有final不可变类型。 因为对象1的final引用类型域只要引用到了实例,就不允许再改变。

这样对象1的域要改变也只有基本类型域了,而基本类型域我们已经完成了克隆。

简而言之,所有实现了Cloneable接口的类都应该有一个公有的方法覆盖从Object类继承而来的clone()方法,此公有方法先调用super.clone(),

得到一个“浅拷贝”的对象,然后根据原对象的实例域的情况,修正任何需要修正的域。一般情况下,这意味这要拷贝任何包含内部“深层结构”

的可变对象。并将新对象的引用代替原来指向这些对象的引用。虽然,这些内部拷贝操作往往可以通过层层递进的调用clone()来完成(要求图中的

Apple类和Dog类也必须正确的提供公有的clone()方法),但这通常不是最佳的方法。如果该类只包含基本类型的域,和不可变类型的引用域,

那么多半情况下是没有域需要修正的。

第十一条:谨慎的覆盖clone()方法的更多相关文章

  1. Effective Java 之-----谨慎的覆盖clone方法

    1.概述 如果clone方法返回一个由构造器创建的对象,它就得到有错误的类.因此,如果覆盖了非final类中的clone方法,则应该返回一个通过调用super.clone得到的对象.如果类的所有超类都 ...

  2. 第11条:谨慎地覆盖clone

    Clone提供一种语言之外的机制:无需调用构造器就可以创建对象. 它的通用约定非常弱: 创建和返回该对象的一个拷贝.这个拷贝的精确含义取决于该对象的类.一般含义是,对于任何对象x,表达式x.clone ...

  3. Effective Java 第三版——13. 谨慎地重写 clone 方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  4. Item 11 谨慎地覆盖Clone

    1.进行浅拷贝时,只是复制原始数据类型的值,则可以通过覆盖Clone方法来达到.另外,在进行浅拷贝的时候,还要注意,成员对象中不应该要有引用类型,如果有引用类型,那么,进行了浅拷贝之后,两个对象将会共 ...

  5. [Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第十---十一条

    第十条 始终覆盖toString() toString的实现可以使类使用起来更加舒适,在执行println等方法时打印出定制信息. 一单实现了自己的toString,指定输出的固定格式,在方法的文档说 ...

  6. Java - 谨慎覆盖clone

    覆盖clone时需要实现Cloneable接口,Cloneable并没有定义任何方法. 那Cloneable的意义是什么? 如果一个类实现了Clonable,Object的clone方法就可以返回该对 ...

  7. Effective Java —— 谨慎覆盖clone

    本文参考 本篇文章参考自<Effective Java>第三版第十三条"Always override toString",在<阿里巴巴Java开发手册>中 ...

  8. 谨慎重载clone方法

    本文涉及到的概念 1.浅拷贝和深拷贝 2..clone方法的作用和使用方式 3.拷贝构造器和拷贝工厂   1.浅拷贝和深拷贝 浅拷贝 一个类实现Cloneable接口,然后,该类的实例调用clone方 ...

  9. jquery中的clone()方法使用

    clone([Even[,deepEven]]) 描述: 克隆匹配的DOM元素并且选中这些克隆的副本. 在想把DOM文档中元素的副本添加到其他位置时这个函数非常有用. 1:一个布尔值(true 或者 ...

随机推荐

  1. H5 EventSource 实现web页面推送功能demo

    /** * H5 EventSource 实现web页面推送功能demo */ var serverData,statusDiv; var SERVER_URL = "index.php&q ...

  2. [BZOJ1061] [Noi2008] 志愿者招募 (费用流)

    Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能 ...

  3. linux里所有命令都不存在

    打开/etc/profile ,看这个配置文件里的PATH变量,遍历这个变量里配置的多个路径,查看命令是否存在. 主要是这四个:/bin ,/usr/bin,/sbin,/usr/sbin. PATH ...

  4. 在lamp上简单部署应用程序

    前言:上文中,说到了lamp的基本原理,apache与php的三种交互模式,php与mysql(mariadb)的交互,一次完整lamp的请求. LAMP简单的部署之后,便能够简单的搭建自己的网站. ...

  5. Linux基础教程(一)——Linux系统简介

    Linux的概述 Linux是基于Unix的开源免费的操作系统,由于系统的稳定性和安全性几乎成为程序代码运行的最佳系统环境.Linux是由Linus Torvalds(林纳斯·托瓦兹)起初开发的,由于 ...

  6. UWP 创建动画的极简方式 — LottieUWP

    提到 UWP 中创建动画,第一个想到的大多都是 StoryBoard.因为 UWP 和 WPF 的界面都是基于 XAML 语言的,所以实现 StoryBoard 会非常方便. 来看一个简单的 Stor ...

  7. View滑动的常见方式

    今天头条的面试官问起了实现View滑动的方式,其实前几天刚刚看过,但还是没能答上来,这里再来总结一遍. 1.使用scrollTo/scrollBy 为了实现View滑动,Android专门提供了这两个 ...

  8. MySQL Connector 卸载

    MySQL Connector 安装的时候有时候会遇到很多问题,有时候会卸载失败,导致无法重新安装.测试了网上各种办法,删文件,删注册表,重启,360强行删除都不是很有效.最后发现msizap比较有效 ...

  9. Unity服务端链接MySQL数据库

    链接数据库,可以分为以下几个流程: 链接MySQL(数据库地址.端口.用户名.密码) 选择数据库 执行sql语句 关闭数据库 转换为代码如下: using System; using MySql.Da ...

  10. google提示恶意软件解决办法

    对于没有安全经验的小白来说 google的一张图可能就会让吓得不轻(我会说我就是小白么~~) 就是这么一张图~ 其实解决办法很简单 google会向用户推荐几款比较不错的软件 进行检测 其中我认为比较 ...