java对象如果想被克隆,它对应的类需要implements标志接口Cloneable。如果不重写clone()方法,则在调用clone()方法实现的是浅复制(所有的引用对象保持不变,意思是如果原型里这些对象发生改变会直接影响到复制对象)。重写clone()方法,一般会先调用super.clone()进行浅复制,然后再复制那些易变对象,从而达到深复制的效果。千言万语不如代码:

public class CloneTest implements Cloneable{

private byte[] a = {1, 2, 3, 4};

private byte[] b = {5, 6, 7, 8};

public CloneTest clone() {

CloneTest copy = null;

try {

copy = (CloneTest) super.clone();

copy.a = this.a.clone();

} catch (CloneNotSupportedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return copy;

}

// 习惯用上面

// @Override

// protected Object clone() throws CloneNotSupportedException {

// // TODO Auto-generated method stub

// CloneTest copy = (CloneTest) super.clone();

// copy.a = this.a.clone();

// return copy;

// }

public byte[] getA() {

return this.a;

}

public byte[] getB() {

return this.b;

}

public static void main(String[] args) {

CloneTest original = new CloneTest();

CloneTest cloned = original.clone();

System.out.println("original.a == cloned.a : " + (original.getA() == cloned.getA()));

System.out.println("cloned.a[3] = " + cloned.getA()[3]);

original.getA()[3] = 9;

System.out.println("cloned.a[3] = " + cloned.getA()[3]);

System.out.println("original.b == cloned.b : " + (original.getB() == cloned.getB()));

System.out.println("cloned.b[3] = " + cloned.getB()[3]);

original.b[3] = 10;

System.out.println("cloned.b[3] = " + cloned.getB()[3]);

}

}

original.a == cloned.a : false

cloned.a[3] = 4

cloned.a[3] = 4

original.b == cloned.b : true

cloned.b[3] = 8

cloned.b[3] = 10

super.clone(),这个操作主要是来做一次bitwise copy( binary copy ),即浅拷贝,他会把原对象完整的拷贝过来包括其中的引用。这样会带来问题,如果里面的某个属性是个可变对象,那么原来的对象改变,克隆的对象也跟着改变。所以在调用完super.clone()后,一般还需要重新拷贝可变对象。

调用super.clone()后返回的对象满足以下:

x.clone != x

x.clone.getClass() == x.getClass()

以下摘录R大在知乎的回答:

JavaDoc这段

* The method {@code clone} for class {@code Object} performs a

* specific cloning operation. First, if the class of this object does

* not implement the interface {@code Cloneable}, then a

* {@code CloneNotSupportedException} is thrown. Note that all arrays

* are considered to implement the interface {@code Cloneable} and that

* the return type of the {@code clone} method of an array type {@code T[]}

* is {@code T[]} where T is any reference or primitive type.

* Otherwise, this method creates a new instance of the class of this

* object and initializes all its fields with exactly the contents of

* the corresponding fields of this object, as if by assignment; the

* contents of the fields are not themselves cloned. Thus, this method

* performs a "shallow copy" of this object, not a "deep copy" operation.

也就是说JavaDoc指明了Object.clone()有特殊的语义,他就是能把当前对象的整个结构完全浅拷贝一份出来。

* By convention, the returned object should be obtained by calling

* {@code super.clone}. If a class and all of its superclasses (except

* {@code Object}) obey this convention, it will be the case that

* {@code x.clone().getClass() == x.getClass()}.

每层clone()都顺着 super.clone() 的链向上调用的话最终就会来到Object.clone() ,于是根据上述的特殊语义就可以有 x.clone.getClass() == x.getClass() 。

至于如何实现的,可以把JVM原生实现的Object.clone()的语义想象成拿到this引用后通过反射去找到该对象实例的所有字段,然后逐一字段拷贝。

HotSpot vm中,Object.clone()在不同的优化层级上有不同的实现。在其中最不优化的版本是这样做的:拿到this引用,通过对象头里记录的Klass信息去找出这个对象有多大,然后直接分配一个新的同样大的空对象并且把Klass信息塞进对象头(这样就已经实现了x.clone.getClass() == x.getClass()这部分语义),然后直接把对象体 的内容看作数组拷贝一样从源对象“盲”拷贝到目标对象,bitwise copy。然后就完事啦。

-----------------------------------------------------------------------------------

我的理解是super.clone() 的调用就是沿着继承树不断网上递归调用直到Object 的clone方法,而跟据JavaDoc所说Object.clone()根据当前对象的类型创建一个新的同类型的空对象,然后把当前对象的字段的值逐个拷贝到新对象上,然后返回给上一层clone() 调用。

也就是说super.clone() 的浅复制效果是通过Object.clone()实现的。

java super.clone解释_super.clone()做了什么相关推荐

  1. java的对象克隆技术clone()之浅度克隆(shallow Clone)

    要使两个对象(栈空间不同)具有相同的属性,需要利用java语言的对象克隆技术.对象克隆就是对象的复制,即完整的复制一个对象.java.lang.Object类的 clone()方法能够实现对象的复制. ...

  2. JAVA程序员工作常用英语(细心整理)java常用名词解释

    java常用名词解释: AAA 认证 (Authentication):验证用户的身份与可使用的网络服务:授权(Authorization):依据认证结果开放网络服务给用户:计帐(Accounting ...

  3. java语言中解释方式是什么意思,Java语言快速入门·简答T

    1 面向对象与面向过程有什么区别? 面向对象编程:既然面向的是对象,那么强调的自然就是--对象,那么对象多了,就会抽象出相应的类(对象是类的实例化),所以 · 程序是由类组成 · 程序运行的时候去调用 ...

  4. java super实例_java Super 用法详解及实例代码

    java Super 用法详解及实例代码 发布于 2021-1-8| 复制链接 摘记: java  Super 用法详解 1)有人写了个很好的初始化属性的构造函数,而你仅仅想要在其中添加另一些自己新建 ...

  5. java语言特点解释类_Java语言特点

    Java语言特点 引导语:Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言.那么你知道Java语言的特点吗,以下是百分网小编分享给大家的Java语言特点,欢迎阅读! Java语言的特点 1 ...

  6. java基础--名词解释汇总

    "专业术语",程序员在对JVM 做任何的性能和垃圾回收调整之前理解和记住这些"专业术语"是非常重要的.那么学习java有哪些专业名词是程序员必须记的呢?下面为大 ...

  7. java同步关键词解释、synchronized、线程锁(Lock)

    1.java同步关键词解释 21.1 synchronized synchronized是用来实现线程同步的!!! 加同步格式: synchronized( 需要一个任意的对象(锁) ){ 代码块中放 ...

  8. Java面试,如何在短时间内做突击

    转载自  Java面试,如何在短时间内做突击 面试技术文 Java岗 面试考点精讲(基础篇01期) Java岗 面试考点精讲(基础篇02期) Java岗 面试考点精讲(网络篇03期) Java 面试中 ...

  9. Java 虚拟机对锁优化所做的努力

    转载自   Java 虚拟机对锁优化所做的努力 作为一款公用平台,JDK 本身也为并发程序的性能绞尽脑汁,在 JDK 内部也想尽一切办法提供并发时的系统吞吐量.这里,我将向大家简单介绍几种 JDK 内 ...

最新文章

  1. COGS2355 【HZOI2015】 有标号的DAG计数 II
  2. SAP Spartacus 的会话管理 Session Management
  3. 『数据库』怎样设计一个数据库
  4. jQuary的相关动画效果
  5. usb接口多少钱_工控机一般有多少个串口
  6. Springboot 配置文件的加载位置以及优先级和外部配置文件加载的优先级
  7. Spring Cloud 负载均衡
  8. dbcc_DBCC FREEPROCCACHE命令介绍和概述
  9. android通知栏内添加快捷键_Android实现向Launcher添加快捷方式的方法
  10. ios之alloc和init
  11. IOS xib 和storyboard的区别
  12. PSPICE仿真数据转MATLAB
  13. android pay和hce区别,一文带你看懂闪付和云闪付的区别
  14. CMake的一些细节
  15. linux如何查看无线密码是多少个,在 Linux 中查看连接过的 WiFi 密码
  16. org.eclipse.wst.common.component
  17. 手把手教你在ARM嵌入式开发板上只做自己的人脸识别装置
  18. 计算机考研复试-离散数学
  19. 计算机企业人员的职称有哪些,企业IT人员评职称需要什么资质
  20. JavaScript一维数组、二维数组的深拷贝

热门文章

  1. vue中前端实现pdf预览(含vue-pdf插件用法)
  2. nginx常用的优化配置
  3. 降维的基本知识点总结
  4. 机器学习---降维算法
  5. 一、TF2 常用命令
  6. VMware虚拟机怎么用U盘装win7系统
  7. jsp第三方小额支付平台
  8. Windows主机间批量操作的基本配置
  9. 印光法师:《灵岩遗旨》壹、悲化有情
  10. onedrive手机客户端_OneDrive手机版