原文地址:http://leihuang.org/2014/11/14/java-clone/

In java, it essentially means the ability to create an object with similar state as the original object.

什么是clone

字典中的意思就是复制(强调跟原来的一模一样)。

*By default, java cloning is ‘field by field copy’ *.由于Object类不知道详细类的结构,无法确定哪个clone方法将被调用。

所以JVM规定clone,做例如以下操作。

  1. 假设这个类仅仅有原始数据类型成员的话。那么须要创建一个一模一样的对象,而且返回这个新对象的引用。
  2. 假设这个类包括了不论什么类类型成员的话,那么仅仅有这些成员的对象引用被复制。且原始对象和克隆对象的成员的引用将指向同一个对象。

翻译的不好。%>_<%

  1. If the class has only primitive data type members then a completely new copy of the object will be created and the reference to the new object copy will be returned.
  2. If the class contains members of any class type then only the object references to those members are copied and hence the member references in both the original object as well as the cloned object refer to the same object.

除了上面两条默认的操作之外。你也能够重载clone方法,制定一套自己的clone方法。


java中clone规则

每种支持clone的语言都有它自己的规则,java也不例外。java中假设一个类需要支持clone的话。必需要做例如以下事情:

  1. 你必须继承Cloneable接口---Cloneable interface is broken in java。otherwise throws java.lang.CloneNotSupportedException.
  2. 必须重写Object类中的clone()方法
/*
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
The general intent is that, for any object x, the expression:
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
*/
protected native Object  [More ...] clone() throws CloneNotSupportedException;

  1. 第一条表明,clone对象分配有独立的内存地址。
  2. 第二条表明,原始的和克隆的对象应该具有同样类型,但这不是必须的
  3. 第三条表明。原始的和克隆的对象调用equals方法的话,应该时相等的。但这不是必须的。

以下我们通过样例来分析:

class Father implements Cloneable{private int age ;private String name ;private Son son ;public Father(int age,String name,Son son){this.age = age ;this.name = name ;this.son = son ;}public Son getSon(){return this.son ;}@Overrideprotected Object clone()throws CloneNotSupportedException{return super.clone() ;}
}
class Son{private int age ;private String name ;public Son(int age ,String name){this.age = age ;this.name = name ;}public void setName(String name){this.name = name ;}public String getName(){return this.name ;}
}
public class CloneDemo {public static void main(String args[]) throws CloneNotSupportedException{Son s = new Son(10,"Jack") ;Father fa = new Father(40,"Tom",s) ;Father clonedFa = (Father) fa.clone() ;System.out.println(fa!=clonedFa);System.out.println(clonedFa.getClass()==fa.getClass());System.out.println(clonedFa.equals(fa));//now we change the fa's son name by the clonedFa's son nameclonedFa.getSon().setName("Jay");System.out.println(fa.getSon().getName());}
}
/*print:
true
true
false
Jay
*/

上面的代码中能够看出。原始的和克隆的Father类对象。拥有指向同一对象的两个引用。所以能够通过改变clonedFa中的Son来改变fa中Son对象。这就时所谓的浅拷贝.以下我们具体讨论一下浅拷贝和深拷贝。

浅拷贝(Shallow Cloning)

这是java中默认的实现。上面的样例中就是浅拷贝。不创建一个新的克隆拷贝对象Son,而是直接两个引用指向同一对象。

深拷贝

If we want a clone which is independent of original and making changes in clone should not affect original.you can try Deep Cloning.

we change the clone() method in the Father class .

@Override
protected Object clone() throws CloneNotSupportedException {Father fa = (Father)super.clone();          fa.setSon((Son)fa.getSon().clone());return fa;
}

and we need Override the clone() method in the Son class. like this.

@Override
protected Object clone() throws CloneNotSupportedException {return super.clone();
}

如今我们已经实现深拷贝了。

拷贝构造函数

拷贝构造函数时一种特殊的构造器。它讲自己的类类型作为參数。我们传递一个类的实例给拷贝构造函数。然后它将返回一个新的类实例。lets see this in example

public class PointOne {private Integer x;private Integer y;public PointOne(PointOne point){this.x = point.x;this.y = point.y;}
}

假设要继承它的话,则须要复制子类的參数,和传递參数给父类的构造器。

例如以下:

public class PointTwo extends PointOne{private Integer z;public PointTwo(PointTwo point){super(point); //Call Super class constructor herethis.z = point.z;}
}

以下是測试代码:

class Test
{public static void main(String[] args){PointOne one = new PointOne(1,2);PointTwo two = new PointTwo(1,2,3);PointOne clone1 = new PointOne(one);PointOne clone2 = new PointOne(two);//Let check for class typesSystem.out.println(clone1.getClass());System.out.println(clone2.getClass());}
}
Output:
class corejava.cloning.PointOne
class corejava.cloning.PointOne

你也能够使用静态工厂的方法来实现它。

public class PointOne {private Integer x;private Integer y;public PointOne(Integer x, Integer y){this.x = x;this.y = y;}public PointOne copyPoint(PointOne point) throws CloneNotSupportedException{if(!(point instanceof Cloneable)){throw new CloneNotSupportedException("Invalid cloning");}//Can do multiple other things herereturn new PointOne(point.x, point.y);}
}

Cloning with serialization

这是例外一种深拷贝的方法。这里就不多讲了,具体见:A mini guide for implementing serializable interface in java

best practices

1) When you don’t know whether you can call the clone() method of a particular class as you are not sure if it is implemented in that class, you can check with checking if the class is instance of “Cloneable” interface as below.

if(obj1 instanceof Cloneable){obj2 = obj1.clone();
}
//Dont do this. Cloneabe dont have any methods
obj2 = (Cloneable)obj1.clone();

2) No constructor is called on the object being cloned. As a result, it is your responsibility, to make sure all the members have been properly set. Also, if you are keeping track of number of objects in system by counting the invocation of constructors, you got a new additional place to increment the counter.

Reference:

  1. A guide to object cloning in java
  2. Effective--Java Item 11: Override clone judiciously(讲的更具体,各种clone方式的优缺点都讲了)

2014-11-14 15:48:12

Brave,Happy,Thanksgiving !

版权声明:本文博主原创文章。博客,未经同意不得转载。

j详细说明ava于clone办法相关推荐

  1. HTML 渲染组件出错,这个问题可以通过安装某个缺失组件来解决。您是否想要了解详细信息? 的解决办法

    问题概述 最近喜欢上了一款文本编辑软件 " Markdownpad 2 " ,非常好用,是一款用起来后无法自拔的!呃 ! 好吧! Markdownpad 2  安装程序的下载备份地 ...

  2. 计算机无法识别读卡器怎么办,usb读卡器读不出来怎么办,详细教您解决的办法...

    随着许多电子产品的普及,目前例如像智能手机.数码照相机.笔记本电脑等等,都在我们生活越来越广泛.而这些产品的共通性,那就是信息都是以数据形式存在的,照片.音乐等等.因此,一个额外的小工具就出现在我们的 ...

  3. webpack 版本冲突详细原因分析及解决办法

    本项目使用vue/cli-4构建,在安装完less-loader后,npm run serve 时候报错,原因是webpack版本冲突 报错信息 Error: Rule can only have o ...

  4. 本地项目提交代码到git仓库详细教程包含错误解决办法!!!

    1.查看远程分支 git branch -r 2.查看本地分支 git branch 二.创建和切换分支 1.创建新分支 git branch 新分支名称 2.切换分支 git checkout 分支 ...

  5. ubuntu下j在安装ava环境

    先执行如下命令,执行完之后,将会安装jdk: sudo apt-get install sun-java6-jdk 然后执行 sudo update-java-alternatives -s java ...

  6. Vercel+Railway部署Typecho动态博客(超详细图文教程-Vercel CLI办法)

    这次讲一下如何用 Vercel 部署 Typecho 动态博客 本文写于 2023 年 1 月 6 日,文中我的问题你可能不会出现,出现其他问题请自行百度 由于我这里有一个玄学问题:Vercel 不能 ...

  7. Premiere不能导入视频怎么办?详细全面的快速解决办法

    Premiere导入视频失败该怎么办? Premiere中想要导入视频,但是却发现导入不进来,总是导入失败,该怎么办呢? 在使用Adobe Premiere的过程中,有可能出现视频文件导入失败的情况. ...

  8. 2021最新 wordpress+xampp+阿里云建站过程(超级详细)

    下面我们来介绍服务器端搭建个人博客详细过程(此处使用本地下载之后再进行上传操作) 首先我们需要的准备事项(本地电脑windows系统,服务器使用阿里云) 限时领取阿里云2000元优惠礼包 XAMPP( ...

  9. word 7桌面上的计算机图标是,怎么设置win7系统桌面图标都变成word图标的处理办法...

    随着电脑的使用率越来越高,我们有时候可能会遇到win7系统桌面图标都变成word图标问题,如果我们遇到了win7系统桌面图标都变成word图标的问题,要怎么处理win7系统桌面图标都变成word图标呢 ...

最新文章

  1. AWS ML deploy platform
  2. 其原因可能是堆被损坏,这也说明 xxx.exe 中或它所加载的任何 DLL 中有 bug
  3. ViewBag与ViewData传值乱码问题解决方案
  4. DPDK vhost库(十一)
  5. 基于 DDD 设计并实现模块化单体应用
  6. 请你简单介绍一下ArrayList和LinkedList的区别及大数据量情况下的插入效率对比
  7. python 爬视频下载_Python爬虫进阶之爬取某视频并下载的实现
  8. 短信宝 php使用,[php] 使用 短信宝 发送短信(thinkphp)
  9. JavaScript复习使用定时器的简易式诸葛大力轮播图
  10. 关于那些表单的验证码
  11. Netty是如何解决粘包和拆包问题的
  12. GaMD-高斯加速分子动力学模拟中文教程
  13. win10 android 手机驱动下载,小米手机驱动win10驱动
  14. Proxmark3的Android客户端,Proxmark3 冰人原版固件及客户端
  15. HBuilderX日常踩坑之隐私合规检测
  16. 代码:灰度重心法提取线激光条纹中心线(CPP+OpenCV)
  17. 51单片机流水灯实验
  18. Fabric.js中文文档
  19. excel二进制移位运算_Excel定位神技能Ctrl+G,10种不可绕开的操作技巧
  20. 三菱化学控股公司:关于代表执行董事的人事变动通知

热门文章

  1. NHibernate重要概念的解释和说明
  2. 一个web左侧菜单例子
  3. Perl一行式:文本编解码、替换
  4. 使用jpcap获取网卡硬件
  5. redis学习(七)jedis客户端
  6. poj 2482 Stars in Your Window (线段树扫描线)
  7. GCD学习之dispatch_barrier_async
  8. 直接拿来用!最火的Android开源项目(完结篇)
  9. UVA 10229 Modular Fibonacci
  10. (转)jQuery第五课:Ajax