Java克隆

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 的克隆或副本。



2,什么时候使用Clone?

      当需要修改对象属性,又不想影响原来的属性值,这时候就应该使用clone了。



3,  Java 对 clone 的支持
1. Clone&Copy 假设现在有一个Employee对象,Employee tobby =new Employee(“CMTobby”,5000),通常我们会有这样的赋值Employee cindyelf=tobby,这个时候只是简单了copy了一下reference,cindyelf和tobby都指向内存中同一个object,这样cindyelf或者tobby的一个操作都可能影响到对方。打个比方,如果我们通过cindyelf.raiseSalary()方法改变了salary域的值,那么tobby通过getSalary()方法得到的就是修改之后的salary域的值,显然这不是我们愿意看到的。我们希望得到tobby的一个精确拷贝,同时两者互不影响,这时候我们就可以使用Clone来满足我们的需求。Employee cindy=tobby.clone(),这时会生成一个新的Employee对象,并且和tobby具有相同的属性值和方法。

2. Shallow Clone&Deep Clone Clone是如何完成的呢?Object在对某个对象实施Clone时对其是一无所知的,它仅仅是简单地执行域对域的copy,这就是Shallow Clone。这样,问题就来了咯,以Employee为例,它里面有一个域hireDay不是基本型别的变量,而是一个reference变量,经过Clone之后就会产生一个新的Date型别的reference,它和原始对象中对应的域指向同一个Date对象,这样克隆类就和原始类共享了一部分信息,而这样显然是不利的,这个时候我们就需要进行deep Clone了,对那些非基本型别的域进行特殊的处理,例如本例中的hireDay。我们可以重新定义Clone方法,对hireDay做特殊处理,如下代码所示:

class Employee implements Cloneable{        

        public Object clone() throws CloneNotSupportedException               

       {                            

                Employee cloned = (Employee) super.clone();                        

                cloned.hireDay = (Date) hireDay.clone();        

                return cloned;                

        }

}

3. Clone()方法的保护机制在Object中Clone()是被申明为protected的,这样做是有一定的道理的,以Employee 类为例,通过申明为protected,就可以保证只有Employee类里面才能“克隆”Employee对象。

4. Clone()方法的使用 Clone()方法的使用比较简单,注意如下几点即可: a. 什么时候使用shallow Clone,什么时候使用deep Clone,这个主要看具体对象的域是什么性质的,基本型别还是reference variable b. 调用Clone()方法的对象所属的类(Class)必须implements Clonable接口,否则在调用Clone方法的时候会抛出CloneNotSupportedException。


      万类之初的  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() :



4,shallow clone  and deep clone

    Clone是如何完成的呢?Object在对某个对象实施Clone时对其是一无所知的,它仅仅是简单地执行域对域的copy,这就是Shallow Clone。Java Collection 类库中具体数据结构类( ArrayList/LinkedList , HashSet/TreeSet , HashMap/TreeMap 等)都具有克隆功能,且都是 Shallow Clone。在有种情况下,这种shallow Clone就会问题,这个情况就是当,要clone的对象中的某个属性是一个引用, 这样克隆类就和原始类共享了一部分信息,对这个属性操作就会影响原始类,所以就需要deep clone.



deep clone的简单例子:

Java代码
public class TestClone {  
 
    /** 
     * @param args 
     */ 
 
    public static void main(String[] args) {  
        try {  
            new TestClone().cloneObject();  
        } catch (CloneNotSupportedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    }  
 
    public void cloneObject() throws CloneNotSupportedException {  
        Person p = new Person();  
        Man man = new Man();  
        man.setSalory("111123");  
        p.setName("zhangfei");  
        p.setMan(man);  
        //man.setSalory("122335");//(1)  
        Person pp = p.getClonePerson(p);  
        man.setSalory("122335");//(2)  
        pp.setName("aa");  
        System.out.println("pp.getName()= " + pp.getName() + " pp.man.getSalory()= "+pp.getMan().getSalory());  
        System.out.println("p.getName()=" + p.getName()+" p.man.getSalory()= "+p.getMan().getSalory());  
    }  
}  
 
class Person implements Cloneable {  
    private String name = "";  
    private Man man;  
      
    public String getName() {  
        return name;  
    }  
 
    public void setName(String name) {  
        this.name = name;  
    }  
 
 
    public Person getClonePerson(Person p) throws CloneNotSupportedException {  
        Person pp = (Person) p.clone();  
        return pp;  
    }  
 
    public Man getMan() {  
        return man;  
    }  
 
    public void setMan(Man man) {  
        this.man = man;  
    }  
      
    public Object clone() throws CloneNotSupportedException{  
        Person p = (Person) super.clone();  
        p.man = this.getMan().getCloneMan(this.getMan());  
        return p;  
    }  
}  
 
class Man implements Cloneable{  
    private String salory = "";  
 
    public String getSalory() {  
        return salory;  
    }  
 
    public void setSalory(String salory) {  
        this.salory = salory;  
    }   
    public Man getCloneMan(Man man) throws CloneNotSupportedException{  
        Man ma = (Man)man.clone();  
        return ma;  
    }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值