java克隆注意事项

  • 对象拷贝时,类的构造函数不会被执行
package PrototypePattern.cloneTest;

public class TestObject implements Cloneable{

    public TestObject() {
        System.out.println("构造函数执行");
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
}


package PrototypePattern.cloneTest;

public class RunDemo {

    public static void main(String[] args) {
        
        TestObject o1 = new TestObject();
        
        try {
            TestObject o2 = (TestObject) o1.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        
    }
    
}

clone方法的原理是在内存中分配一个内存块,以二进制流的方式进行拷贝。

  • 浅克隆:只拷贝本对象,对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址。而其他的基本数据类型和String类型则都会被拷贝。
package PrototypePattern.cloneTest;

import java.util.ArrayList;
import java.util.List;

public class TestObject implements Cloneable{
    
    private List arrayList = new ArrayList();

    public List getArrayList() {
        return arrayList;
    }

    public void addItem(String item) {
        this.arrayList.add(item);
    }

    public TestObject() {
        System.out.println("构造函数执行");
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
}


package PrototypePattern.cloneTest;

public class RunDemo {

    public static void main(String[] args) {
        
        TestObject o1 = new TestObject();
        o1.addItem("HaHaHa");
        
        try {
            TestObject o2 = (TestObject) o1.clone();
            o2.addItem("HeiHeiHei");
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        
        System.out.println(o1.getArrayList());
        
    }
    
}

java克隆注意事项_第1张图片

对象o1和o2的arrayList对象都是指向同一个内存地址,所以o2对象的arrayList添加的元素实际上是添加到o1对象的arrayList属性中。

  • 深克隆:在拷贝对象的时候,将对象内的数组、引用对象一起显式拷贝。或者也可以通过写二进制流来实现深克隆。

深克隆示例中arrayList属性在声明的时候不是List类型的了,而是ArrayList类型。因为ArrayList实现了Cloneable接口,而List没有,所以要使用clone方法,必须使用ArrayList。

package PrototypePattern.cloneTest;

import java.util.ArrayList;
import java.util.List;

public class TestObject implements Cloneable{
    
    private ArrayList arrayList = new ArrayList();

    public List getArrayList() {
        return arrayList;
    }

    public void addItem(String item) {
        this.arrayList.add(item);
    }

    public TestObject() {
        System.out.println("构造函数执行");
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        TestObject o2 = null;
        o2 = (TestObject) super.clone();
        o2.arrayList = (ArrayList)this.arrayList.clone();
        return o2;
    }
    
}


package PrototypePattern.cloneTest;

public class RunDemo {

    public static void main(String[] args) {
        
        TestObject o1 = new TestObject();
        o1.addItem("HaHaHa");
        
        try {
            TestObject o2 = (TestObject) o1.clone();
            o2.addItem("HeiHeiHei");
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        
        System.out.println(o1.getArrayList());
        
    }
    
}

参考文档:《设计模式之禅》

你可能感兴趣的:(Java)