最近看到了一个关于使用Object clone()方法进行复制的例子,对这个有点疑问,不知道大家怎么使用这个问题的呢?拿出来讨论一下,hoooo~  
最好拿个例子出来讨论一下,满意送分!

解决方案 »

  1.   

    clone就是对象的复制,在某些场合可以代替new操作,并且能带来性能上更好的效果,以下是摘自CSDN的“qj_peng的专栏”,具体地址:http://blog.csdn.net/qj_peng/archive/2007/05/14/1608298.aspxjava clone
    有时我们确实需要clone一个对象,最好的方法还是使用Object的clone方法,由jdk调用native方法来实现,这样效率比较高。先来个shallow clone,再来deep clone。
     
    shallow clone
     
     
    代码如下:
    待clone的对象
     
    package practisejava.others.clone;
     
    /**
     * 待clone的对象,必须实现Cloneable这个tag interface
     */
    public class ObjectToClone implements Cloneable{
       private int i=0;
     
       public void setNum(int i){
           this.i=i;
       }
     
       public int getNum(){
           return this.i;
       }
      
       public void tellNum(){
           System.out.println("the number is "+i);
       }
       // 重写Object的clone
       public Object clone() throws CloneNotSupportedException {
            return (ObjectToClone)super.clone();
        }
    }
    clone测试
     
    package practisejava.others.clone;
     
    /**
     * 测试clone是否成功
     */
    public class CloneTest {
        public static void main(String[] args) {
            ObjectToClone otc = new ObjectToClone();
            otc.setNum(888);
          
            // 开始clone了!
            ObjectToClone cloneObject = null;
            try {
                cloneObject = (ObjectToClone) otc.clone();
            } catch (CloneNotSupportedException ex) {
                System.out.println("Sorry,Clone Not Supported!");
            }
          
            // 测试clone是否成功
            if(cloneObject!=null){
                System.out.println("before clone");
                System.out.println("ObjectToClone get number : " + otc.getNum()+"\n");
          
                System.out.println("after clone");
                System.out.println("ObjectToClone get number : " + otc.getNum());
              
                cloneObject.setNum(999);
                System.out.println("CloneObject get number : " + cloneObject.getNum());
            }      
        }
    }
    执行结果
     
    before clone
    ObjectToClone get number : 888
     
    after clone
    ObjectToClone get number : 888
    CloneObject get number : 999
     
     
     
    从运行结果看,修改了clone体的值并没有影响到原来被clone体的值,哈哈,clone成功。高兴得太早了,ObjectToClone里只有简单的非引用属性,如果有引用的属性,还能成吗?答案是否定的!看下面的例子:
    被clone对象引用的对象
      

  2.   

    package practisejava.others.shallowclone;
     
    public class ReferencedObject {
        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;
        }
    }
     
     
    待clone对象
     
    package practisejava.others.shallowclone;
     
    /**
     * 必须实现Cloneable接口,否则调用函数的clone方法时会报CloneNotSupportedException错
     */
    public class ObjectForShallowClone 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 {
             return (ObjectForShallowClone)super.clone();
         }
    }  
    clone测试
     
    package practisejava.others.shallowclone;
     
    /**
     * clone测试
     */
    public class CloneTest {
        public static void main(String[] args) {
            ObjectForShallowClone ofsc = new ObjectForShallowClone();
            ofsc.setNum(888);
            ofsc.setReferencedObject(new ReferencedObject(1));
     
            // 开始clone了!
            ObjectForShallowClone deepCloneObject = null;
            try {
                deepCloneObject = (ObjectForShallowClone) 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("ObjectForShallowClone get number : " + ofsc.getNumber());
                System.out.println("ObjectForShallowClone ReferencedObject get number : " + ofsc.getReferencedObject().getNumber());
     
                System.out.println("CloneObject get number : " + deepCloneObject.getNumber());
                System.out.println("CloneObject ReferencedObject get number : " + deepCloneObject.getReferencedObject().getNumber());
            }      
        }
    }
     
    运行结果如下:
     
    before clone
    ObjectForShallowClone get number : 888
    ObjectForShallowClone ReferencedObject get number : 1
     
    after clone
    ObjectForShallowClone get number : 888
    ObjectForShallowClone ReferencedObject get number : 2
    CloneObject get number : 999
    CloneObject ReferencedObject get number : 2
     
     
     
    显然,修改了clone对象的引用对象的值后,被clone对象引用对象的值也随之改变。这不是我们想要的效果,改进的方法就是deep clone。
    deep clone
    被clone对象引用的对象(比shallow clone多加了clone的方法)
     
    package practisejava.others.deepclone;
     
    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;
        }
     
        // 重写clone的方法
        public Object clone() throws CloneNotSupportedException {
            return (ReferencedObject)super.clone();
        }
    }
    待clone对象(在clone方法里同时clone引用对象)
     
    package practisejava.others.deepclone;
     
    import practisejava.others.deepclone.ReferencedObject;
     
    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;
         }
    }
    clone测试
     
    package practisejava.others.deepclone;
     
    public class CloneTest {
        public static void main(String[] args) {
            ObjectForDeepClone ofdc = new ObjectForDeepClone();
            ofdc.setNum(888);
            ofdc.setReferencedObject(new ReferencedObject(1));
     
            // 开始clone了!
            ObjectForDeepClone deepCloneObject = null;
            try {
                deepCloneObject = (ObjectForDeepClone) ofdc.clone();
            } catch (CloneNotSupportedException ex) {
                System.out.println("Sorry,Clone Not Supported!");
            }
     
            // 测试clone是否成功
            if(deepCloneObject!=null){
                System.out.println("before clone");
                System.out.println("ObjectForDeepClone get number : " + ofdc.getNumber());
                System.out.println("ObjectForDeepClone ReferencedObject get number : "+ofdc.getReferencedObject().getNumber()+"\n");
     
                deepCloneObject.setNum(999);
                deepCloneObject.getReferencedObject().doubleValue();
     
                System.out.println("after clone");
                System.out.println("ObjectForDeepClone get number : " + ofdc.getNumber());
                System.out.println("ObjectForDeepClone ReferencedObject get number : " + ofdc.getReferencedObject().getNumber());
     
                System.out.println("CloneObject get number : " + deepCloneObject.getNumber());
                System.out.println("CloneObject ReferencedObject get number : " + deepCloneObject.getReferencedObject().getNumber());
            }
        }
    }
     
     
     
     
     
    运行结果:
     
    before clone
    ObjectForDeepClone get number : 888
    ObjectForDeepClone ReferencedObject get number : 1
     
    after clone
    ObjectForDeepClone get number : 888
    ObjectForDeepClone ReferencedObject get number : 1
    CloneObject get number : 999
    CloneObject ReferencedObject get number : 2
     
     
     
    Clone 通常有两种类型即浅clone和深clone。首先,分析一下两种的不同。浅clone和深clone都是clone,它们本质区别是对象内部的成员属性(非原生类型属性,如int等)在clone时是否处理为引用。如果仍然保留为引用,则称为浅clone,反之称为深clone。其实这两个概念也是相对的概念。在处理上它们有点区别,浅clone方式得到clone对象即可,深clone方式在得到clone对象后,还需要对引用的成员属性进行 “clone”处理。从这个层次上说,深clone并没有什么特别地困难,简单讲就是创建好对象,再设置一些成员属性。
      

  3.   

    上面说的深度clone就是被clone对象中所有的引用类型的成语变量自身也要实现clone方法,这个应该不难理解
      

  4.   

    事实上,clone的应用场合不多,几乎可以不用。