這裏咱們就能夠引入兩個專業的術語:淺克隆(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{
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); } }