`
fuwa_jane
  • 浏览: 50080 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java克隆方法的研究(clone)

    博客分类:
  • Java
阅读更多

本文摘自:http://blog.csdn.net/it_man/archive/2006/11/22/1404550.aspx




 什么是"clone"?

  在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。在Java语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。

  Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。

  怎样应用clone()方法?

  一个很典型的调用clone()代码如下:

class CloneClass implements Cloneable{ 
 public int aInt; 
 public Object clone(){ 
  CloneClass o = null; 
  try{ 
   o = (CloneClass)super.clone(); 
  }catch(CloneNotSupportedException e){ 
   e.printStackTrace(); 
  } 
  return o; 
 } 
} 


 有三个值得注意的地方,一是希望能实现clone功能的CloneClass类实现了Cloneable接口,这个接口属于java.lang包,java.lang包已经被缺省的导入类中,所以不需要写成java.lang.Cloneable。另一个值得请注意的是重载了clone()方法。最后在clone()方法中调用了super.clone(),这也意味着无论clone类的继承结构是什么样的,super.clone()直接或间接调用了java.lang.Object类的clone()方法。下面再详细的解释一下这几点。

  应该说第三点是最重要的,仔细观察一下Object类的clone()一个native方法,native方法的效率一般来说都是远高于java中的非native方法。这也解释了为什么要用Object中clone()方法而不是先new一个类,然后把原始对象中的信息赋到新对象中,虽然这也实现了clone功能。对于第二点,也要观察Object类中的clone()还是一个protected属性的方法。这也意味着如果要应用clone()方法,必须继承Object类,在Java中所有的类是缺省继承Object类的,也就不用关心这点了。然后重载clone()方法。还有一点要考虑的是为了让其它类能调用这个clone类的clone()方法,重载之后要把clone()方法的属性设置为public。

  那么clone类为什么还要实现Cloneable接口呢?稍微注意一下,Cloneable接口是不包含任何方法的!其实这个接口仅仅是一个标志,而且这个标志也仅仅是针对Object类中clone()方法的,如果clone类没有实现Cloneable接口,并调用了Object的clone()方法(也就是调用了super.Clone()方法),那么Object的clone()方法就会抛出CloneNotSupportedException异常。

  以上是clone的最基本的步骤,想要完成一个成功的clone,还要了解什么是"影子clone"和"深度clone"。

  什么是影子clone?

  下面的例子包含三个类UnCloneA,CloneB,CloneMain。CloneB类包含了一个UnCloneA的实例和一个int类型变量,并且重载clone()方法。CloneMain类初始化UnCloneA类的一个实例b1,然后调用clone()方法生成了一个b1的拷贝b2。最后考察一下b1和b2的输出:

package clone; 
class UnCloneA { 
 private int i; 
 public UnCloneA(int ii) { i = ii; } 
 public void doublevalue() { i *= 2; } 
 public String toString() { 
  return Integer.toString(i); 
 } 
} 
class CloneB implements Cloneable{ 
 public int aInt; 
 public UnCloneA unCA = new UnCloneA(111); 
 public Object clone(){ 
  CloneB o = null; 
  try{ 
   o = (CloneB)super.clone(); 
  }catch(CloneNotSupportedException e){ 
   e.printStackTrace(); 
  } 
  return o; 
 } 
} 
public class CloneMain { 
 public static void main(String[] a){ 
  CloneB b1 = new CloneB(); 
  b1.aInt = 11; 
  System.out.println("before clone,b1.aInt = "+ b1.aInt); 
  System.out.println("before clone,b1.unCA = "+ b1.unCA); 

  CloneB b2 = (CloneB)b1.clone(); 
  b2.aInt = 22; 
  b2.unCA.doublevalue(); 
  System.out.println("================================="); 
  System.out.println("after clone,b1.aInt = "+ b1.aInt); 
  System.out.println("after clone,b1.unCA = "+ b1.unCA); 
  System.out.println("================================="); 
  System.out.println("after clone,b2.aInt = "+ b2.aInt); 
  System.out.println("after clone,b2.unCA = "+ b2.unCA); 
 } 
} 

/** RUN RESULT: 
before clone,b1.aInt = 11 
before clone,b1.unCA = 111 
================================= 
after clone,b1.aInt = 11 
after clone,b1.unCA = 222 
================================= 
after clone,b2.aInt = 22 
after clone,b2.unCA = 222 
*/ 


  输出的结果说明int类型的变量aInt和UnCloneA的实例对象unCA的clone结果不一致,int类型是真正的被clone了,因为改变了b2中的aInt变量,对b1的aInt没有产生影响,也就是说,b2.aInt与b1.aInt已经占据了不同的内存空间,b2.aInt是b1.aInt的一个真正拷贝。相反,对b2.unCA的改变同时改变了b1.unCA,很明显,b2.unCA和b1.unCA是仅仅指向同一个对象的不同引用!从中可以看出,调用Object类中clone()方法产生的效果是:先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。

  大多时候,这种clone的结果往往不是我们所希望的结果,这种clone也被称为"影子clone"。要想让b2.unCA指向与b2.unCA不同的对象,而且b2.unCA中还要包含b1.unCA中的信息作为初始信息,就要实现深度clone。
分享到:
评论

相关推荐

    Java中的克隆(Clone)机制

    Java中的克隆(Clone)机制,很少涉及的内容。

    java克隆对象(两种方法)

    java的两种深度克隆方法,1cloneTest是用Cloneable接口的clone方法实现(对象必须要实现cloneable接口).2cloneSerialize.java是用对象流写对象到byte数组中,然后从byte数组中取得对象.(对象必须要实现serializble接口)

    浅析Java中clone()方法浅克隆与深度克隆

    Java克隆(Clone)是Java语言的特性之一,本篇文章主要介绍了Java中的Clone机制是如何工作的,需要的朋友可以参考下

    java中clone的用法实例

    clone的用法 希望有帮助,仅供参考 通过例子的分析,可以对克隆的方法有所深入了解

    darts-clone-java:用Java编写的DARTS(Double-ARray Trie System)克隆

    darts-clone-java 用Java编写的Double-ARray Trie System克隆。 该库基于称为“快速高效”库的 。入门设置要使用Maven添加依赖项,请使用以下命令: < dependency> < groupId>...

    初级java笔试题-clone:克隆

    初级java笔试题编程面试大学 我最初创建它是为了成为一名软件工程师的学习主题的简短待办事项列表,但它增长到您今天看到的大列表。 完成这个学习计划后,! 你可能不需要像我一样学习。 总之,你需要的都在这里。 ...

    java 中clone()的使用方法

    主要介绍了java 中clone()的使用方法的相关资料,希望通过本文能帮助大家能掌握clone()的克隆方法,需要的朋友可以参考下

    java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】

    * 需要被克隆的 class类, 重写Object中的clone()方法,并实现Cloneable接口(否则报错 CloneNotSupportedException) * 注意: * 1.被克隆对象.clone()出的对象,是被克隆对象的当前状态 * 2.被克隆对象 如果...

    对象克隆(clone)详解.docx

    查看了很多文章对于clone()方法讲解都不慎透彻,特别是对于深层克隆的讲解语言晦涩难懂,很难理解,包括Oracle公司出版的JDK帮助文档也讲的不清楚,本人通过具体实践通过浅显易懂的语言详细讲解了clone()方法。...

    深入理解Java中的克隆

    想必大家对克隆都有耳闻,世界上第一只克隆羊多莉就是利用细胞核移植技术将哺乳动物的成年体细胞培育出新个体,甚为神奇。...本文将尝试介绍一些关于Java中的克隆和一些深入的问题,希望可以帮助大家更好地了解克隆。

    bigcoder84#study-notes#_4Object中的clone方法1

    Object类中的clone方法clone()方法的作用克隆方法用于创建对象的拷贝,为了使用clone方法,类必须实现java.lang.Cloneable接口

    J2SE笔记讲解个人修订(1.1).docx

    1 JAVA认识 2 JAVA数据类型 3 面向对象程序设计 4 JAVA集合 5 JAVA反射机制 6 JAVA注解(ANNOTATION) 7 JAVA中的异常类 ...20 JAVA克隆CLONE(复制) 21 JAVA 网络编程 22 JAVA 其他未归类 23 JNI概述

    tetris-clone:用 Java 制作的俄罗斯方块的克隆

    Java 制作的俄罗斯方块的克隆#####特征一切都是可调整大小的(可在 Well.class 文件中配置) 易于修改,因为所有的部分和颜色都是从文件中导入的使用简单的手Craft.io术#####用法克隆存储库 git clone ...

    medium-clone:Medium.com的完整堆栈应用程序克隆

    随着越来越多的人试图找到一种展现自己诗意的一面的方法,Poedium努力实现自己的梦想。 有关此项目的更多信息,请访问 讲台 诗人的社区 目录 关于该项目 一个完整的堆栈应用程序,可从medium.com汲取灵感。 实时...

    java编程常见问题

    当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出该异常。 47.java.lang.EnumConstantNotPresentException 枚举常量不存在异常。当应用试图通过名称和枚举类型访问一个枚举对象,但该枚举对象...

    java 编程入门思考

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

    Java初学者入门教学

    12.2.5 Object.clone()的效果 12.2.6 克隆合成对象 12.2.7 用Vector进行深层复制 12.2.8 通过序列化进行深层复制 12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 ...

    facebook-clone:study Facebook界面的UI克隆,用于研究目的

    Java脚本 后端 Node.js Express.js Nodemon Dotenv 修女 注:后端技术被用来部署到Heroku的,它们并没有反映在应用上直接开发。 :laptop: 项目 出于学习目的,使用html,css和javascript制作的facebook界面的...

    Java利用序列化实现对象深度clone的方法

    主要介绍了Java利用序列化实现对象深度clone的方法,实例分析了java序列化及对象克隆的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下

Global site tag (gtag.js) - Google Analytics