EffectiveJava(11)Java中的clone

java中的clone

clone构造器及其静态工厂的变形
优点:它们不依赖于某一种很有风险的,语言之外的对象创建机制;
它们不要求遵守尚未制定好文档的规范
他们不会于final域的正常使用发生冲突
它们不会抛出不必要的受检异常
它们不需要进行类型转换

/**
* 1.必须继承Cloneable接口
* 2.必须重写Object类中的clone()方法 –
* Cloneable接口改变了接口的通用规范,它改变了超类中受保护的方法的行为
* –无需构造器就可以创建对象
* a.clone对象分配有独立的内存地址 – x.clone()!=x;
* b.原始的克隆对象应该具有相同类型 x.clone().getClass == x.getClass 非必需
* c.原始的克隆对象调用equals方法的话,应该是相等的 非必需
* @author JacXuan
*
*/

public class Father implements Cloneable{
    private int age;
    private String name;
    private Son son;

    public Father(int age,String name,Son son){
        this.age = age;
        this.name = name;
        this.son = son;
    }

    public Son getSon(){
        return this.son;
    }
    public void setSon(Son son){
        this.son = son;
    }
    /**
     * 浅拷贝代码--
     * 原始对象和克隆对象拥有指向同一对象的两个引用,所以可以通过改变cloneFather
     * 中的Son来改变father中的Son对象
     * @throws CloneNotSupportedException 
     */
//  @Override
//  public Object clone() throws CloneNotSupportedException{
//      return super.clone();
//  }   

    /**
     * 深拷贝 -- 在Son中实现clone方法  return super.clone();
     */
    @Override
    public Object clone() throws CloneNotSupportedException{
        Father father = (Father)super.clone();
        father.setSon((Son)father.getSon().clone());
        return father;
    }
}


    Son son  = new Son(20, "PG");
        Father father = new Father(40, "JacX", son);

            Father cloneFather = (Father)father.clone();
            System.out.println(father!=cloneFather);
            System.out.println(cloneFather.getClass() == father.getClass());
            System.out.println(cloneFather.equals(father));


2.package com.object.equals.clone.conctr;

/**
 * 拷贝构造函数 -- 一种特殊的构造器
 * 它将自己的类类型作为参数  传递一个类的实例给拷贝构造函数,
 * 然后他将返回一个新的类实例
 * @author JacXuan
 *
 */
public class CloneConctr {
    private Integer x;
    private  Integer y;

    public CloneConctr(CloneConctr cloneConctr){
        this.x = cloneConctr.x;
        this.y=cloneConctr.y;
    }

//  public CloneConctr copyPoint(CloneConctr cloneConctr) throws CloneNotSupportedException{
//      if(!(cloneConctr instanceof Cloneable)){
//          throw new CloneNotSupportedException("Invalid clone");
//      }
//  
//      //可以做多种其他事情
//      return new CloneConctr(cloneConctr.x,cloneConctr.y);
//  }

/**
 * 最佳实践
 *1)当你不知道你是否可以调用clone()方法的类你不确定如果是在这个类中实现,
 *您可以检查和检查如果类的实例“可克隆”界面如下。
 */
    //  if(obj instanceof Cloneable){
    //obj2 = obj.clone();
    //}
    //Dont do this. Cloneabe dont have any methods
    //obj2 = obj.clone();   
}

package com.object.equals.clone.conctr;

/**
 * 如果要继承它的话,则需要复制子类的参数并传递参数给父类的构造器
 * @author JacXuan
 *
 */
public class CloneConctr2 extends CloneConctr{
    private Integer z;

    public CloneConctr2(CloneConctr2 cloneConctr2){
        super(cloneConctr2);
        this.z = cloneConctr2.z;
    }
}

3.package com.object.equals.clone.hashtable;

/**
 * 解决克隆对象和原有对象引用链表相同引起的数据篡改 单独地拷贝并组成每个桶的链表
 * 如果链表比较长,容易导致栈溢出
 * @author JacXuan
 *
 */
public class HashTable implements Cloneable {
    private Entry[] buckets = null;

    private static class Entry {
        final Object key;
        Object value;
        Entry next;

        Entry(Object key, Object value, Entry next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        Entry deepCopy() {
            //深度克隆  如果桶是空的,则clone下一个
            return new Entry(key, value, next == null ? null : next.deepCopy());
        }
    }

    @Override
    public HashTable clone() throws CloneNotSupportedException {
        HashTable result = (HashTable) super.clone();
        result.buckets = new Entry[buckets.length];
        for (int i = 0; i < buckets.length; i++) {
            if (buckets[i] != null) {
                result.buckets[i] = buckets[i].deepCopy();
            }
        }
        return result;
    }

}
原文地址:https://www.cnblogs.com/qwop/p/6637302.html