EffectiveJava-第11条 谨慎地覆盖克隆clone分析二

克隆有“浅层克隆”、深层克隆,什么情况下需要深层克隆,个人有点想法,且看代码:
  public class DeepClone implements Cloneable {

    private int type;
    private final String special;
    private Flower aflower;
    private int size = 0;
    
    private Flower[] elements;//DeepClone自己管理这部分内存
  

    public DeepClone(int type, String special, Flower flower) {
        this.type = type;
        this.special = special;
        this.aflower = flower;
        this.elements = new Flower[10];
    }
  
    public void push(Flower e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        Object result = elements[--size];
        elements[size] = null; // Eliminate obsolete reference
        return result;
    }

    public boolean isEmpty() {
        return size == 0;
    }
 // Ensure space for at least one more element.
    private void ensureCapacity() {
        if (elements.length == size)
            elements = Arrays.copyOf(elements, 2 * size + 1);
    }
    @Override
    public Object clone() {
        try {
            DeepClone result = (DeepClone) super.clone();
            result.elements=this.elements.clone();//(2)
            return result;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
    
    public static void main(String[] arr) {
     
        Flower flower = new Flower();
        flower.setName("Red flower");
        DeepClone source = new DeepClone(10, "GG", flower);
        
        Flower yellow = new Flower();
        yellow.setName("Yellow");
        Flower[] arrs=new Flower[]{yellow};         
        for (Flower arg : arrs)
            source.push(arg);
        
        
        System.out.println("----------源对象花朵名称---------" + source.aflower.getName());        
        DeepClone copy = (DeepClone) source.clone();
        System.out.println("----------克隆的对象花朵名称---------" + copy.aflower.getName());
        System.out.println("------source==copy------------"+(source==copy));
       
        source.type=0;
        System.out.println("----------源对象type值变化---------" + source.type);
        System.out.println("----------克隆的对象type值未发生变化,仍然为10---------" + copy.type);        
        source.aflower=null;
        System.out.println("----------源对象花朵名称变化---------" + (source.aflower==null?"null":source.aflower.getName()));
        System.out.println("----------克隆的对象花朵引用未发生变化---------" + (copy.aflower==null?"null":copy.aflower.getName()));
        
        //elements,DeepClone自己管理的内存部分
        //如果没有(2)的深层克隆,copy的elements不是克隆一份,而是原有elements的引用
        Object sourcePop=null;
        while (!source.isEmpty()){
            sourcePop=source.pop();
            System.out.println("------source elements------------"+((Flower)sourcePop).getName()); 
            
        }        
        Object copyPop=null;
        while (!copy.isEmpty()){
            copyPop=copy.pop();
            System.out.println("------copy elements------------"+((Flower)copyPop).getName());
            
        }
        System.out.println("------sourcePop==copyPop------------"+(sourcePop==copyPop));
    }
}

通过对DeepClone的测试分析,目前有如下结论:

(1)对象域需要“深层克隆”。
(2)对象数组域需要“深层克隆”。
(3)与stack的Object[] elements类似, Flower[] elements域由于是被克隆类DeepClone自己管理的数组;
  在DeepColen被克隆时必须“深层克隆”,result.elements=this.elements.clone()才能确保克隆对象有另外一份elements数组(可能是内存地址的指针)。 

你可能感兴趣的:(EffectiveJava)