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

Java Clone机制

阅读更多
1          什么是 Clone ,容易实现吗?

简单地说, Clone 就是对于给定的一个对象实例 o ,得到另一个对象实例 o’ : o 与 o’ 类

型相同( o.getClass() == o’.getClass() ),内容相同(对于 o/o’ 中的字段 f ,如果 f 是基本数据类型,则 o.f == o’.f ;如果 f 是对象引用,则 o.f == o’.f 或 o.f 指向的对象与 o’.f 指向的对象的内容相同)。通常称 o’ 为 o 的克隆或副本。

       直观上看,似乎很容易为一个类加上 clone 方法:
class A {

       private Type1 field1;

    private Type2 field2;

     …..

    public Object clone() {

              A a = new A();

        a.field1 = a.getField1();

        a.field2 = a.getField2();

        ……

        return a;

    }

}

然而,稍加推敲,就会发现这样的实现方法有两个问题:

1.         要想某个类有 clone 功能,必须单独为其实现 clone() 函数,函数实现代码与该类定义密切相关。

2.         即使基类 A 已有 clone() 函数,其子类 ExtendA 若要具备 clone 功能,则必须 override 其基类 A 的 clone() 函数。否则,对类型为 ExtendA 的对象 ea 的 clone() 方法的调用,会执行于类 A 中定义的 clone() 方法而返回一个类型为 A 的对象,它显然不是 ea 的克隆。
2          Java 对 clone 的支持

万类之初的 Object 类有 clone() 方法:

protected native Object clone() throws CloneNotSupportedException;

该方法是 protected 的,显然是留待被子类 override 的。该方法又是 native 的,必然做了

与具体平台相关的底层工作。

事实上,类 Object 的 clone() 方法首先会检查 this.getClass() 是否实现了 Cloneable 接口。

Cloneable 只是一个标志接口而已,用来标志该类是否有克隆功能。

public interface Cloneable {

}

       如果 this.getClass() 没有实现 Cloneable 接口, clone() 就会抛 CloneNotSupportedException 返回。否则就会创建一个类型为 this.getClass() 的对象 other ,并将 this 各 field 的值赋值给 other 的对应 field ,然后返回 other 。

       如此一来,我们要定义一个具有 Clone 功能的类就相当方便:

1.         在类的声明中加入“ implements Cloneable ”,标志该类有克隆功能;

2.         Override 类 Object 的 clone() 方法,在该方法中调用 super.clone() :


class CloneableClass implements Cloneable {

       ……

public Object clone() {

       try {

              return super.clone(); // 直接让 Object.clone() 为我们代劳一切

    } catch (CloneNotSupportedException e) {

              throw new InternalError();

       }

}

}

3          Shallow Clone 与 Deep Clone
3.1     Shallow 与 Deep 从何而来

一个具有克隆功能的类,如果有可变( Mutable )类类型的字段 field ,如何为其克隆(副

本)对象 o’ 中的 field 赋值?

       方法一、如 Object 的 clone() 方法所实现:设原始对象为 o ,其克隆对象是 o’ ,执行 o’.field = o.field 。这样, o’.field 与 o.field 指向同一个可变对象 m 。 o 与 o’ 可能会相互影响(一个对象的状态可能会随着另一个对象的状态的改变而改变)。这样的 Clone 称为 Shallow Clone 。这也是 Object 的 clone() 方法的实现方式。

       方法二、将 o.field 指向的可变对象 m 克隆,得到 m’ ,将 m’ 的引用赋值给 o’.field 。这样 o’ 与 o 内容相同,且相互之间无影响(一个对象状态的改变不会影响另一个对象的状态)。这样的 Clone 称为 Deep Clone 。

       Java Collection 类库中具体数据结构类( ArrayList/LinkedList , HashSet/TreeSet , HashMap/TreeMap 等)都具有克隆功能,且都是 Shallow Clone ,这样设计是合理的,因为它们不知道存放其中的每个数据对象是否也有克隆功能。 System.arrayCopy() 的实现采用的也是 Shallow Clone 。

       Deep Clone 对于实现不可变( Immutable )类很有帮助。设一个类包含可变类 M 类型的 field ,如何将其设计为不可变类呢?先为 M 实现 Deep Clone 功能,然后这样设计类 ImmutableClass :
class ImmutableClass {

       MutableClass m;

ImmutableClass(MutableClass m) {

       this.m = m.clone(); // 将传入的 m 的 clone 赋值给内部 m

}

public MutableClass getM() {

    return this.m.clone(); // 将内部 m 的 clone 返回给外部

}

}

3.2     如何实现 Deep Clone

检查类有无可变类类型的字段。如果无,返回 super.clone() 即可;

如果有,确保包含的可变类本身都实现了 Deep Clone ;

Object o = super.clone(); // 先执行浅克隆,确保类型正确和基本类型及非可变类类型字段内容正确

对于每一个可变类类型的字段 field :

       o.field = this.getField().clone();

返回 o 。
分享到:
评论

相关推荐

    Java中的克隆(Clone)机制

    现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生这个词语确实很“火”过一阵子,在java中也有这么一个概念,它可以让我们很方便的“制造”出一个对象的副本来,下面来具体看看java中的Clone机制是如何工作的...

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

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

    Clone详解.doc

    现在Clone已经不是一个新鲜词语了,伴随着“多莉”的产生这个词语确实很“火”过一阵子,在java中也有这么一个概念,它可以让我们很方便的“制造”出一个对象的副本来,下面来具体看看java中的Clone机制是如何工作的...

    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概述

    java面试题.pdf

    3. Java中垃圾回收的机制是什么? 4. Java中什么是反射? 5. Java中什么是线程安全? 6. Java中抽象类和接口的区别是什么? 7. Java中什么是异常? 8. Java中如何防止对象的clone? 9. Java中什么是泛型? 10. Java...

    Java-JDK、数据库系统开发、Web开发学习笔记

    Java-JDK、数据库系统开发、Web开发学习笔记 ...本文档涵盖了Java-JDK的基础知识,包括Object类的方法、异常类的层次结构、Java反射机制、集合类等内容,为Java开发者提供了一个全面了解Java基础知识的机会。

    GitHub 上标星 115k+ 的 Java 教程.pdf

    Autoboxing 是 Java 中的一种机制,用于将基本数据类型自动转换为对应的包装类。Unboxing 是 Autoboxing 的逆过程,用于将包装类转换为基本数据类型。例如,使用 Integer x = 2; 就会自动将 int 类型的 2 转换为 ...

    java语言程序设计 java编程笔记 由浅入深的笔记 共32份 全套资源.rar

    clone.docx Date日期.docx GC垃圾回收机制.docx instanceof运算符.docx io.docx java基础关键字.docx java命名和数据类型.docx java序列化.docx Math类.docx Object(对象).docx operator(运算符).docx ...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    Java编程老鸟潜心写作,奉献高效率的Java学习心得 完全站在没有编程经验读者的角度,手把手教会读者学习Java 配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让...

    200个Java经典面试题总结附带答案.docx

    (Java 反射机制,可以在运行时访问和修改类的信息) 15. 什么是 Java 序列化?什么情况下需要序列化?(序列化是将对象转换为字节流,用于网络传输或持久化) Java 异常 16. `throw` 和 `throws` 的区别?(`...

    Java面试资料之IO相关

    Java IO 是 Java 语言中的一种基本输入/输出机制,用于实现数据的读取和写入。本文将从流的分类、流的转换、对象序列化、字节流和字符流的区别、对象克隆等方面对 Java IO 进行总结。 1. 流的分类 Java 中有两种...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    Java编程老鸟潜心写作,奉献高效率的Java学习心得 完全站在没有编程经验读者的角度,手把手教会读者学习Java 配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让...

    Java面试宝典2017.zip

    23、java中实现多态的机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 18 26、什么是内部类?Static Nested ...

    java面试宝典

    46、java 中实现多态的机制是什么? 12 47、在java 中一个类被声明为final 类型,表示了什么意思? 12 48、下面哪些类可以被继承? 12 49、指出下面程序的运行结果: 【基础】 13 52、关于内部类: 13 53、数据类型...

    Java面试宝典-经典

    43、Java中的异常处理机制的简单原理和应用。 28 44、请写出你最常见到的5个runtime exception。 28 45、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出...

    java 面试题 总结

    assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为...

    Java面试宝典2010版

    43、Java中的异常处理机制的简单原理和应用。 28 44、请写出你最常见到的5个runtime exception。 28 45、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出...

    如何编出健壮的代码,java编程30条规则

    规则 2: 在创建一个类时,请采取“经典形式”,并包含对下述元素的定义:equals()、hashCode()、toString()、clone()(implement Cloneable)、implement Serializable。这条规则对类的基本结构进行了规定,使得类...

    java面试题大全(2012版)

    43、Java中的异常处理机制的简单原理和应用。 28 44、请写出你最常见到的5个runtime exception。 28 45、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出...

Global site tag (gtag.js) - Google Analytics