java面试基础-Java中对Clone的理解

面试中经常遇到Clone的相关知识,今天总算是把Clone理解的比较透彻了!Java中Clone的概念大家应该都很熟悉了,它可以让我们很方便的“制造”出一个对象的副本来,下面来具体看看java中的Clone机制是如何工作的?

1. Clone和Copy

 假设现在有一个User对象,User u1=new User(“U1001”,“Jason”,25),通

常我们会有这样的赋值User u2=u1,这个时候只是简单了copy了一下reference,u2和u1都指向内存中同一个object,这样u2或者u1的一个操作都可能影响到对方。打个比方,如果我们通过u2.setAge()方法改变了Age域的值,那么u1通过getAge()方法得到的就是修改之后的Age域的值,显然这不是我们愿意看到的。我们希望得到u1的一个精确拷贝,同时两者互不影响,这时候我们就可以使用Clone来满足我们的需求。User u2=u1.clone(),这时会生成一个新的User对象,并且和u1具有相同的属性值和方法。

2. Shallow Clone和Deep Clone

Clone是如何完成的呢?Object在对某个对象实施Clone时对其是一无所知的,它仅仅是简单地执行域对域的copy,这就是Shallow Clone。这样,问题就来了咯,以User为例,它里面有一个域birthday不是基本型别的变量,而是一个reference变量,经过Clone之后就会产生一个新的Date型别的reference,它和原始对象中对应的域指向同一个Date对象,这样克隆类就和原始类共享了一部分信息,而这样显然是不利的,过程下图所示:

这个时候我们就需要进行deep Clone了,对那些非基本型别的域进行特殊的处理,例如本例中的birthday。我们可以重新定义Clone方法,对birthday做特殊处理,如下代码所示:
Java代码 收藏代码

 class User implements Cloneable  
    {  
         public Object clone() throws CloneNotSupportedException  
         {  
           User cloned = User super.clone();  
           cloned.birthday = (Date) hireDay.clone()  
           return cloned;  
         }  
    }  

3. Clone()方法的保护机制在Object中Clone()是被申明为protected的,这样做是有一定的道理的,以User类为例,通过申明为protected,就可以保证只有User类里面才能“克隆”User对象,原理可以参考我前面关于public、protected、private的学习笔记。

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

来一个深度的,不过这也不深,还可以克到五段,六段!

package com.colorme.t20.deepclone;
/**
* 被克隆对象里包含的引用类
* @author lcc
* @version 2017-07-11
*/

public class ReferencedObject implements Cloneable{
    private int i = 0;
    public ReferencedObject(int i) {
        this.i = i;
    }
    public void doubleValue(){
        this.i = 2*this.i;
    }

    public int getNumber(){
        return this.i;
    }

public  Object clone() throws CloneNotSupportedException {
return super.clone();
}


}

package com.feixun.t20.deepclone;

/**
* 带引用的克隆
* @author lcc
* @version 2017-07-11
*/
public class ObjectForDeepClone  implements Cloneable{
    private int i = 0;
    private ReferencedObject rf = null;

    public void setNum(int i) {
        this.i = i;
    }

    public void setReferencedObject(ReferencedObject rf){
        this.rf = rf;
    }

    public int getNumber(){
        return this.i;
    }

    public ReferencedObject getReferencedObject(){
        return this.rf;
    }

    // 重写Object的clone
    public Object clone() throws CloneNotSupportedException {
    ObjectForDeepClone cloneObject=(ObjectForDeepClone)super.clone();
    // 调用引用对象的clone方法
        if(rf!=null){
            ReferencedObject rfClone = (ReferencedObject)rf.clone();
            cloneObject.setReferencedObject(rfClone);
        }

         return cloneObject;
     }
}  

package com.feixun.t20.deepclone;

import java.io.Serializable;

public class CloneTest {

    public static void main(String[] args) {
        ObjectForDeepClone ofsc = new ObjectForDeepClone();
        ofsc.setNum(888);
        ofsc.setReferencedObject(new ReferencedObject(1));

        // 开始clone了!
        ObjectForDeepClone deepCloneObject = null;
        try {
            deepCloneObject = (ObjectForDeepClone) ofsc.clone();
        } catch (CloneNotSupportedException ex) {
            System.out.println("Sorry,Clone Not Supported!");
        }

        // 测试clone是否成功
        if(deepCloneObject!=null){
            System.out.println("before clone");
            System.out.println("ObjectForShallowClone get number : " + ofsc.getNumber());
            System.out.println("ObjectForShallowClone ReferencedObject get number : "+ofsc.getReferencedObject().getNumber()+"\n");

            deepCloneObject.setNum(999);
            deepCloneObject.getReferencedObject().doubleValue();

            System.out.println("after clone");
            System.out.println("CloneObject get number : " + deepCloneObject.getNumber());
            System.out.println("CloneObject ReferencedObject get number : " + deepCloneObject.getReferencedObject().getNumber());

            System.out.println();
            System.out.println("ObjectForShallowClone get number : " + ofsc.getNumber());
            System.out.println("ObjectForShallowClone ReferencedObject get number : " + ofsc.getReferencedObject().getNumber());
        }      
    }
}

理解有误之处,还望高 手 指 点!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值