本文引自:http://blog.sina.com.cn/s/blog_605f78830102uy6x.html
1.先來看一段代碼:
List<A> source = new ArrayList<A>();
List<A> copy = new ArrayList<A>();
A a = new A();
a.setName("ABC“);
source.add(a);
copy.addAll(source); //通過addAll()方法拷貝
copy.get(0).setName("CDE");
這時,獲取source.get(0)的name值,也變成了“CDE”。
為了解決這個問題,使得改變copy中的值,不影響source中的數(shù)據(jù),則要進(jìn)行深拷貝。
即,對A類實現(xiàn)clone()方法:
public class A implements Cloneable{
private String name;
public A(){
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
//實現(xiàn)這個方法
protected A clone() throws CloneNotSupportedException {
return (A)super.clone();
}
}
然后,
for(int i = 0; i < source.size();i++){
copy.add(source.get(i).clone());
}
就可以進(jìn)行深拷貝了。
在此,再多描述一下關(guān)于Clone的內(nèi)容。
Java對對象和基本數(shù)據(jù)類型的處理是不一樣的。在Java中用對象作為入口參數(shù)的傳遞則缺省為“引用傳遞”,也就是說僅僅傳遞了對象的一個“引用”,這個引用的概念與C語言中的指針引用是一樣的。當(dāng)函數(shù)體內(nèi)部對這個變量進(jìn)行改變時,實質(zhì)上就是對這個對象進(jìn)行直接操作。
除此之外,在任何用“=”向?qū)ο笞兞抠x值的時候都是“引用傳遞”。
一、當(dāng)Class A的成員變量類型是基本數(shù)據(jù)類型(外加String類型)時,只要實現(xiàn)如上簡單的clone(稱影子clone)就可以。但是如果Class A的成員變量是數(shù)組或者更復(fù)雜類型時,就必須實現(xiàn)深度clone。
public class A implements Cloneable{
private String[] name;
public A(){
name = new String[2];
}
public void setName(String[] name){
this.name = name;
}
public String[] getName(){
return name;
}
//實現(xiàn)這個方法
protected A clone() throws CloneNotSupportedException {
return (A)super.clone();
}
}
此處的A的成員變量String[],影子clone對name數(shù)組clone他們的地址,需進(jìn)行深拷貝。
protected A clone() throws CloneNotSupportedException {
A a = (A)super.clone();
a.name = (String[])name.clone();
return a;
}
二、需要注意的是,Class A存在更為復(fù)雜的成員變量時,如Vector等存儲對象地址的容器時,就必須clone徹底。
public class A implements Cloneable{
private String[] name;
private Vector<B> claB;
public A(){
name = new String[2];
claB = new Vector<B>();
}
public void setName(String[] name){
this.name = name;
}
public String[] getName(){
return name;
}
public void setClaB(Vector<B> claB){
this.claB = claB;
}
public Vector<B> getClaB(){
return claB;
}
protected A clone() throws CloneNotSupportedException {
A a = (A)super.clone();
a.name = (String[])name.clone();
a.claB = new Vector<B>();
for(int i = 0;i < claB.size();i++){
a.claB.add((B)claB.get(i).clone());//當(dāng)然Class B也要實現(xiàn)相應(yīng)clone方法
}
return a;
}
}