java clone

java 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对象引用的对象

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

哇,成功!

 
Java中,对象克隆可以通过两种方式实现:浅克隆克隆。 浅克隆是指创建一个新的对象,该对象的字段与原始对象相同。但如果字段是引用类型,那么新对象与原始对象将引用相同的引用类型对象。换句话说,新对象原始对象共享相同的引用类型字段,对其中一个对象所做的更改会影响另一个对象。 要实现浅克隆,需要在要克隆的类中实现Cloneable接口,并重写Object类的clone()方法。以下是一个示例: ```java public class MyClass implements Cloneable { private int myField; public Object clone() throws CloneNotSupportedException { return super.clone(); } // 其他代码... } ``` 使用浅克隆时,可以通过调用clone()方法来创建一个新对象: ```java MyClass original = new MyClass(); MyClass clone = (MyClass) original.clone(); ``` 深克隆是指创建一个新的对象,并且递归地克隆其所有字段,包括引用类型字段。这样,新对象与原始对象完全独立,对其中一个对象所做的更改不会影响另一个对象。 要实现深克隆,需要在要克隆的类中实现Serializable接口,并使用序列化反序列化来实现深复制。以下是一个示例: ```java import java.io.*; public class MyClass implements Serializable { private int myField; private MyReferenceType reference; public Object deepClone() throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bis); return in.readObject(); } // 其他代码... } ``` 使用深克隆时,可以通过调用deepClone()方法来创建一个新对象: ```java MyClass original = new MyClass(); MyClass clone = (MyClass) original.deepClone(); ``` 需要注意的是,深克隆要求对象及其引用类型字段都必须实现Serializable接口。而且,深克隆可能会影响性能,因为它涉及序列化反序列化的过程。因此,在使用克隆时需要谨慎考虑其适用性性能影响。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值