Java對象淺克隆、深克隆及序列化

這裏咱們就能夠引入兩個專業的術語:淺克隆(shallow clone)和深克隆(deep clone)。 java

所謂的淺克隆,顧名思義就是很表面的很表層的克隆,若是咱們要克隆Administrator對象,只克隆他自身以及他包含的全部對象的引用地址。而深克隆,就是非淺克隆。克隆除自身之外全部的對象,包括自身所包含的全部對象實例。至於深克隆的層次,由具體的需求決定,也有「N層克隆」一說。可是,全部的基本(primitive)類型數據,不管是淺克隆仍是深克隆,都會進行原值克隆。畢竟他們都不是對象,不是存儲在堆中。(Java中全部的對象都是保存在堆中,而堆是供全局共享的。也就是說,若是同一個Java程序的不一樣方法,只要能拿到某個對象的引用,引用者就能夠隨意的修改對象的內部數據。) 數組

要讓一個對象進行克隆,其實就是兩個步驟:1. 讓該類實現java.lang.Cloneable接口;2. 重寫(override)Object類的clone()方法。(而且在方法內部調用持有對象的clone()方法;若是有N多個持有的對象,那就要寫N多的方法,忽然改變了類的結構,還要從新修改clone()方法。) ide

public class CloneBean implements Serializable,Cloneable{
 private String st1 ;
 private int i;
 
 public String getSt1() {
  return st1;
 }
 public void setSt1(String st1) {
  this.st1 = st1;
 }
 public int getI() {
  return i;
 }
 public void setI(int i) {
  this.i = i;
 }
 
 //能夠實現自身的 值克隆  ,若是在父類的克隆的時候, 顯示的調用自身的克隆,並複製給
 @Override
 public Object clone() {
  CloneBean cb = null;
  try {
   cb = (CloneBean) super.clone();//要調用 父類的 clone方法
  } catch (CloneNotSupportedException e) {
   e.printStackTrace();
  }
  return cb;
 }
}

 

public class ShallowClone implements Cloneable {
 // 基本類型  每一個對象一份
 private int a;
 private String b;
 
 // 非基本類型  數組 對象, 複製的對象保持一個引用,相關的修改都會影響
 private int[] c;
 private CloneBean clonebean;
 
 // 重寫Object.clone()方法,並把protected改成public    《只是淺克隆, 若是要實現真正的深克隆,用到 序列化及反序列化》
 @Override
 public Object clone() {
  ShallowClone sc = null;
  try {
   sc = (ShallowClone) super.clone();//要調用 父類的 clone方法
  } catch (CloneNotSupportedException e) {
   e.printStackTrace();
  }
  
  //sc.clonebean=(CloneBean)clonebean.clone();  顯示的調用 對象的克隆,也能夠保持對象的新值,由於 自己對象又是一個新的對象
  
  return sc;
 } this

 public int getA() {
  return a;
 } spa

 public void setA(int a) {
  this.a = a;
 } 對象

 public String getB() {
  return b;
 } 接口

 public void setB(String b) {
  this.b = b;
 } get

 public int[] getC() {
  return c;
 } it

 public void setC(int[] c) {
  this.c = c;
 } io

 public CloneBean getClonebean() {
  return clonebean;
 }

 public void setClonebean(CloneBean clonebean) {
  this.clonebean = clonebean;
 }

}

 

public class ShallowCloneTest {
 public static void main(String[] args) throws CloneNotSupportedException {
  ShallowClone c1 = new ShallowClone();
  // 對c1賦值
  c1.setA(100);
  c1.setB("clone1");
  c1.setC(new int[] { 1000 });
  CloneBean cb = new CloneBean();
  cb.setI(10);
  cb.setSt1("str1");
  c1.setClonebean(cb);

  System.out.println("克隆前: c1.a=" + c1.getA());
  System.out.println("克隆前: c1.b=" + c1.getB());
  System.out.println("克隆前: c1.c[0]=" + c1.getC()[0]);
  System.out.println("克隆前: c1.cb.str1=" + c1.getClonebean().getSt1());
  
  System.out.println("-----------");

  // 克隆出對象c2,並對c2的屬性A,B,C進行修改
  ShallowClone c2 = (ShallowClone) c1.clone();
  // 對c2進行修改
  c2.setA(50);
  c2.setB("clone2");
  int[] a = c2.getC();
  a[0] = 500;
  c2.setC(a);
  
  CloneBean cb1 = c2.getClonebean();
  cb1.setSt1("tewtstewt");
  c2.setClonebean(cb1);

  System.out.println("克隆後: c1.a=" + c1.getA());
  System.out.println("克隆後: c1.b=" + c1.getB());
  System.out.println("克隆後: c1.c[0]=" + c1.getC()[0]);
  System.out.println("克隆後: c1.cb.str1=" + c1.getClonebean().getSt1());
  System.out.println("---------------");

  System.out.println("克隆後: c2.a=" + c2.getA());
  System.out.println("克隆後: c2.b=" + c2.getB());
  System.out.println("克隆後: c2.c[0]=" + c2.getC()[0]);
  System.out.println("克隆後: c2.cb.str1=" + c2.getClonebean().getSt1());
 }
}

×××××××××××××××××××××用serializable來實現×××××××××××××××××××××××××××××××××××

//前提是對象以及對象內部 全部引用到的對象 都是可串行化的,不然,就須要仔細考察那些不可串行化的對象能否設成transient,從而將之排除在複製過程以外。而類變量 是全局的,也不做序列化操做。
public class DeepClone implements Serializable
{
 private static final long serialVersionUID = -4371342386287259388L;
 
    private  transient String transi;//修飾爲不可瞬時的 不可序列化對象
 public static int k;
 
 private int a;
    private String b;
   
    private int[] c;
    private CloneBean cb;//必須也是可串行化的
   
    public int getA()
    {
        return a;
    }
    public void setA(int a)
    {
        this.a = a;
    }
    public String getB()
    {
        return b;
    }
    public void setB(String b)
    {
        this.b = b;
    }
    public int[] getC()
    {
        return c;
    }
    public void setC(int[] c)
    {
        this.c = c;
    }
 public CloneBean getCb() {
  return cb;
 }
 public void setCb(CloneBean cb) {
  this.cb = cb;
 }
 public String getTransi() {
  return transi;
 }
 public void setTransi(String transi) {
  this.transi = transi;
 }
 public static int getK() {
  return k;
 }
 public static void setK(int k) {
  DeepClone.k = k;
 }

 // 用序列化與反序列化實現深克隆  public Object deepClone() {   Object o = null;   try {    ByteArrayOutputStream baos = new ByteArrayOutputStream();    ObjectOutputStream oos = new ObjectOutputStream(baos);    oos.writeObject(this);    oos.close();    ByteArrayInputStream bais = new ByteArrayInputStream(baos      .toByteArray());    ObjectInputStream ois = new ObjectInputStream(bais);    o = ois.readObject();    ois.close();   } catch (IOException e) {    e.printStackTrace();   } catch (ClassNotFoundException e) {    e.printStackTrace();   }   return o;  }     }

// 全部的對象 都必須 實現 序列化接口 public class DeepCloneTest {  public static void main(String[] args) throws CloneNotSupportedException     {         DeepClone dc1 = new DeepClone();         // 對dc1賦值         dc1.setA(100);         dc1.setB("clone1");         dc1.setC(new int[] { 1000 });         CloneBean cb = new CloneBean();         cb.setSt1("deepClone...before...");         dc1.setCb(cb);                 dc1.setTransi("transiant before");         DeepClone.k=100;                 System.out.println("克隆前: dc1.a=" + dc1.getA());         System.out.println("克隆前: dc1.b=" + dc1.getB());         System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]);         System.out.println("克隆前: dc1.cd.str1=" + dc1.getCb().getSt1());                 System.out.println("克隆前: dc1.transiant=" + dc1.getTransi());         System.out.println("克隆前: dc1.k=" + DeepClone.k);                 System.out.println("-----------");         //序列化的全部對象 都要 實現 序列化接口         DeepClone dc2 = (DeepClone)dc1.deepClone();         // 對c2進行修改         dc2.setA(50);         dc2.setB("clone2");         int[] a = dc2.getC();         a[0] = 500;         dc2.setC(a);         CloneBean cb2 = dc2.getCb();         cb2.setSt1("deepClone...after...");         dc2.setCb(cb2);                 System.out.println(dc2.getTransi());    //null值 沒有進行復用         System.out.println(DeepClone.k);         //靜態代碼塊 不用串行化,自己就是公用一塊區域         dc2.setTransi("transiant after");         DeepClone.k=200;                 System.out.println("克隆前: dc1.a=" + dc1.getA());         System.out.println("克隆前: dc1.b=" + dc1.getB());         System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]);         System.out.println("克隆前: dc1.cd.str1=" + dc1.getCb().getSt1());         System.out.println("克隆前: dc1.transiant=" + dc1.getTransi());         System.out.println("克隆前: dc1.k=" +  DeepClone.k);                 System.out.println("-----------");         System.out.println("克隆後: dc2.a=" + dc2.getA());         System.out.println("克隆後: dc2.b=" + dc2.getB());         System.out.println("克隆後: dc2.c[0]=" + dc2.getC()[0]);         System.out.println("克隆後: dc1.cd.str1=" + dc2.getCb().getSt1());         System.out.println("克隆後: dc2.transiant=" + dc2.getTransi());         System.out.println("克隆後: dc2.k=" +  DeepClone.k);     } }
相關文章
相關標籤/搜索