`
esperanza
  • 浏览: 183367 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA的克隆

阅读更多

什么是"clone"

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

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

代码范例:

class CloneB implements Cloneable{

    public int bi = 99;

    public String bs;

    public UnCloneA ua = new UnCloneA("original_a",111);

    public Object clone(){

        CloneB o = null;

        try{

            o = (CloneB)super.clone();

        }catch (CloneNotSupportedException e) {

            e.printStackTrace();

        }

        return o;

    }

}

  有三个值得注意的地方,一是希望能实现clone功能的类要实现了Cloneable接口,这个接口是个标识接口,没有需要实现的方法。另一个值得请注意的是覆盖了clone()方法,并且要留意的是clone()方法是继承自Object的,此方法在Object中是protect的,只能被子类调用。我们实现某个类的克隆功能时就要覆盖这个方法,实现起来很简单的,就是调用super.clone(),具体的克隆工作交给Object

"影子clone""深度clone"

代码范例:

public class CloneTest {

    public static void main(String[] a){

        CloneB b1 = new CloneB();

        b1.bs = "original_b";

        System.out.println("before clone,b1.aStr------>" + b1.bs);

        System.out.println("before clone,b1.bi------>" + b1.bi);

        System.out.println("before clone,b1.unCA------>" + b1.ua);

       

        CloneB b2 = (CloneB)b1.clone();

        b2.bs = "clone_b";

        b2.ua.change();

        b2.ua.mul(3);

        System.out.println("after clone,b1.bs------>" + b1.bs);

        System.out.println("after clone,b1.bi------>" + b1.bi);

        System.out.println("after clone,b1.ua------>" + b1.ua);

        System.out.println("after clone,b2.bs------>" + b2.bs);

        System.out.println("after clone,b2.bi------>" + b2.bi);

        System.out.println("after clone,b2.ua------>" + b2.ua);

       

    }

}

 

class UnCloneA implements Cloneable{

    public int ai = 100;

    public String as;

    public UnCloneA(String as,int ai){

        this.as = as;

        this.ai = ai;

    }

    public void change(){

        as = "cloned_" + as;

    }

    public void mul(int i){

        ai = i*ai;

    }

    public String toString(){

        return as + "@" + ai;

    }

//  public Object clone(){

//      UnCloneA o = null;

//      try{

//          o = (UnCloneA)super.clone();

//      }catch (CloneNotSupportedException e) {

//          e.printStackTrace();

//      }

//      return o;

//  }

}

 

class CloneB implements Cloneable{

    public int bi = 99;

    public String bs;

    public UnCloneA ua = new UnCloneA("original_a",111);

    public Object clone(){

        CloneB o = null;

        try{

            o = (CloneB)super.clone();

//          o.ua = (UnCloneA)ua.clone();

        }catch (CloneNotSupportedException e) {

            e.printStackTrace();

        }

        return o;

    }

}

执行结果:

before clone,b1.aStr------>original_b

before clone,b1.bi------>99

before clone,b1.unCA------>original_a@111

after clone,b1.bs------>original_b

after clone,b1.bi------>99

after clone,b1.ua------>cloned_original_a@333

after clone,b2.bs------>clone_b

after clone,b2.bi------>99

after clone,b2.ua------>cloned_original_a@333

 

把注释去掉后的执行结果:

before clone,b1.aStr------>original_b

before clone,b1.bi------>99

before clone,b1.unCA------>original_a@111

after clone,b1.bs------>original_b

after clone,b1.bi------>99

after clone,b1.ua------>original_a@111

after clone,b2.bs------>clone_b

after clone,b2.bi------>99

after clone,b2.ua------>cloned_original_a@333

         第一次的输出结构表明,修改克隆对象b2int,String等基本类型时,不会对原始对象b1造成影响。就可以理解为,在堆中以及为这些变量开辟了内存空间,把b1的值导入到b2中了。对比2次的输出结果会发现,第一种情况下修改的b2中的UnCloneA对象对b1造成了影响。这就因为b2中并没有UnCloneA的一个实例,只是简单的复制了一个引用,指向了b1中的UnCloneA实例。这就是影子克隆了。如果向让b2中存放一个真正的UnCloneA实例克隆,那就要进行深度克隆,把代码中的注释去掉即可。

分享到:
评论

相关推荐

    java克隆入门和深入

    java克隆技术的入门及深入研究,帮助读者更好的理解java克隆技术,掌握关键知识点。

    java克隆对象(两种方法)

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

    java 深度克隆的代码实例实战理解

    可以更好的去理解java克隆的运用,尤其在多线程的运用过程中,多个对象进行操作过程中,可以先进行对 对象进行 备份,首先就克隆一份,当多线程对对象操作过程中,与异常情况,可以对对象进行恢复,克隆还其他的用途,学会...

    Java中的克隆(Clone)机制

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

    Pong:Pong 的 Java 克隆

    乒乓这是 Pong 的一个非常简单的 Java 克隆,我将它作为一个项目来应用我在 Java 图形编程中学到的东西。 这是众多尝试中的一个,因为我大部分时间都在不知道自己在做什么(自从我最初创建这个克隆以来已经进行了...

    java 深克隆浅克隆

    在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并拥有一个完全独立的新实例,而不是仅仅引用原始对象。克隆技术在处理复杂数据结构、避免对象共享以及实现对象复制等方面有着广泛的应用。...

    克隆和序列化(Java )

    在Java编程语言中,克隆和序列化是两个重要的概念,它们在数据处理和对象管理中扮演着关键角色。下面将分别对这两个概念进行详细解释,并结合实例和源代码进行阐述。 **一、克隆** 1. **克隆定义**:克隆是指创建...

    java 深克隆与浅克隆

    Java 深克隆与浅克隆 Java 中的克隆机制可以让我们方便地制造出一个对象的副本来,但是在克隆过程中需要注意浅克隆和深克隆的区别。 浅克隆(Shallow Clone)是指对对象的域进行简单的 copy,对象的reference变量...

    java二次开发源码下载-Phoenix:消逝的太阳皇帝游戏的Java克隆/重制/补丁

    克隆/重制/补丁。 本软件按“原样”分发,不提供任何类型的明示或暗示的保证或条件。 使用原始 EFS 数据文件并需要安装 EFS 1.4。 应该适用于所有模组。 (可能比本文档更易于导航。) 如果您有一个适用于 EFS 但不...

    java 深克隆 浅克隆

    在Java编程语言中,克隆是一种创建对象副本的方法,它允许我们复制一个对象并得到一个与原对象相同但独立的新对象。克隆分为两种主要类型:深克隆和浅克隆。理解这两种克隆的区别是Java面向对象编程中的重要概念。 ...

    java的深度克隆的例子

    在Java编程语言中,"深度克隆"是一个重要的概念,主要涉及到对象复制。深度克隆,也称为完全克隆,是指创建一个与原对象相同的新对象,不仅复制原对象的所有属性,还复制了原对象中引用的对象。这通常用于创建一个...

    java深度克隆

    ### Java深度克隆知识点详解 #### 一、深度克隆概念 在Java中,深度克隆是一种用于创建对象副本的方法,它可以确保复制出的新对象与原对象之间没有任何引用关系,也就是说,新对象中的所有成员变量(包括引用类型)...

    JAVA浅克隆与深克隆

    在Java编程语言中,克隆是创建一个对象副本的过程,这个副本与原对象有相同的属性值,但作为不同的对象存在。克隆分为两种主要类型:浅克隆(Shallow Clone)和深克隆(Deep Clone)。这篇博客文章将探讨这两种克隆...

    Java对象的复制克隆

    Java中的对象复制与克隆是程序开发中常见的需求,主要用于创建一个对象的副本,而不会影响原始对象的状态。这里主要讨论两种类型的对象拷贝:浅拷贝和深拷贝。 浅拷贝,也称为表面拷贝,是创建一个新的对象,然后将...

    深入理解Java中的克隆

    Java中的克隆是一种复制对象的方式,它允许创建一个与原对象具有相同属性的新对象。在Java中,克隆是通过`Object`类的`clone()`方法实现的,但使用克隆时有一些特定的要求和限制。 首先,为了能够克隆一个对象,该...

    CastleGame:“ Wesnoth之战”的Java克隆

    城堡游戏“ Wesnoth之战”的Java克隆单位可以移动一定数量的步骤。 有不同类型的单位,每个单位都有自己的攻击和防御等级。 玩家只能在视线范围内看到敌方单位。 游戏功能包括:随机生成的游戏场,战争迷雾和战斗...

Global site tag (gtag.js) - Google Analytics