本文引自: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");
這時(shí),獲取source.get(0)的name值,也變成了“CDE”。
為了解決這個(gè)問題,使得改變copy中的值,不影響source中的數(shù)據(jù),則要進(jìn)行深拷貝。
即,對(duì)A類實(shí)現(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;
}
//實(shí)現(xiàn)這個(gè)方法
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對(duì)對(duì)象和基本數(shù)據(jù)類型的處理是不一樣的。在Java中用對(duì)象作為入口參數(shù)的傳遞則缺省為“引用傳遞”,也就是說僅僅傳遞了對(duì)象的一個(gè)“引用”,這個(gè)引用的概念與C語(yǔ)言中的指針引用是一樣的。當(dāng)函數(shù)體內(nèi)部對(duì)這個(gè)變量進(jìn)行改變時(shí),實(shí)質(zhì)上就是對(duì)這個(gè)對(duì)象進(jìn)行直接操作。
除此之外,在任何用“=”向?qū)ο笞兞抠x值的時(shí)候都是“引用傳遞”。
一、當(dāng)Class A的成員變量類型是基本數(shù)據(jù)類型(外加String類型)時(shí),只要實(shí)現(xiàn)如上簡(jiǎn)單的clone(稱影子clone)就可以。但是如果Class A的成員變量是數(shù)組或者更復(fù)雜類型時(shí),就必須實(shí)現(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;
}
//實(shí)現(xiàn)這個(gè)方法
protected A clone() throws CloneNotSupportedException {
return (A)super.clone();
}
}
此處的A的成員變量String[],影子clone對(duì)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ù)雜的成員變量時(shí),如Vector等存儲(chǔ)對(duì)象地址的容器時(shí),就必須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也要實(shí)現(xiàn)相應(yīng)clone方法
}
return a;
}
}