1.先来看一段代码:
1 2 3 4 5 6 7
| 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中的数据,则要进行深拷贝。
即,对A类实现clone()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class A implements Cloneable{ private String name; public A(){ }
public void setName(String name){ this.name = name; }
public String getName(){ return name; }
protected A clone() throws CloneNotSupportedException { return (A)super.clone(); } }
|
然后,
1 2 3
| for(int i = 0; i < source.size();i++){ copy.add(source.get(i).clone()); }
|
就可以进行深拷贝了。
在此,再多描述一下关于Clone的内容。
Java对对象和基本数据类型的处理是不一样的。在Java中用对象作为入口参数的传递则缺省为“引用传递”,也就是说仅仅传递了对象的一个“引用”,这个引用的概念与C语言中的指针引用是一样的。当函数体内部对这个变量进行改变时,实质上就是对这个对象进行直接操作。
除此之外,在任何用“=”向对象变量赋值的时候都是“引用传递”。
一、当Class A的成员变量类型是基本数据类型(外加String类型)时,只要实现如上简单的clone(称影子clone)就可以。但是如果Class A的成员变量是数组或者更复杂类型时,就必须实现深度clone。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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; }
protected A clone() throws CloneNotSupportedException { return (A)super.clone(); } }
|
此处的A的成员变量String[],影子clone对name数组clone他们的地址,需进行深拷贝。
1 2 3 4 5
| protected A clone() throws CloneNotSupportedException { A a = (A)super.clone(); a.name = (String[])name.clone(); return a; }
|
二、需要注意的是,Class A存在更为复杂的成员变量时,如Vector等存储对象地址的容器时,就必须clone彻底。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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()); } return a; } }
|