- 緣起:
昨天辦公室裡同事在問我有關JDK5以上有關泛型集合拷貝操作的問題,他的需求是希望能保留原始集合內所有物件之內容,因此先將原始的集合先行拷貝一份至記憶體內,然後針對這份拷貝出來的集合在行修改操作,這樣一來既可以保留原來的那一份,又可以毫無顧慮地對拷貝出來的這份恣意地修改。
- 問題
但是問題是當他使用集合的拷貝方法時,如:ArrayList.clone()時,Java似乎並沒有真的在記憶體內,重新拷貝新的集合到另一快新的記憶體區塊內。導致他怎麼操作修改新的那份集合,都會連帶異動到原始集合內的資料。
- 解法
簡單地說,以Dog這個類別為例,就是要實作Cloneable這個介面的clone()方法即可。
範例程式碼如下:
- Dog.java
public class Dog implements Cloneable {private String kind;private String color;public Dog(String kind, String color) {super();this.kind = kind;this.color = color;}public String getKind() {return kind;}public void setKind(String kind) {this.kind = kind;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}protected Object clone() throws CloneNotSupportedException {return super.clone();}}
- ListCloneTest.java
import java.util.ArrayList;public class ListCloneTest {/*** @param args* @throws CloneNotSupportedException*/public static void main(String[] args) throws CloneNotSupportedException {// TODO Auto-generated method stubArrayListoldDogs = new ArrayList (); ArrayListnewDogs; oldDogs.add(new Dog("a", "white"));oldDogs.add(new Dog("b", "block"));newDogs = new ArrayList(oldDogs.size()); for(Dog dog : oldDogs){newDogs.add((Dog) dog.clone());}newDogs.get(0).setColor("yellow");newDogs.get(1).setKind("d");System.out.println("Old Dogs#1 : kink="+oldDogs.get(0).getKind()+" color="+oldDogs.get(0).getColor());System.out.println("New Dogs#1 : kink="+newDogs.get(0).getKind()+" color="+newDogs.get(0).getColor());System.out.println("Old Dogs#2 : kink="+oldDogs.get(1).getKind()+" color="+oldDogs.get(1).getColor());System.out.println("New Dogs#2 : kink="+newDogs.get(1).getKind()+" color="+newDogs.get(1).getColor());}}
- 輸出結果:
Old Dogs#1 : kink=a color=whiteNew Dogs#1 : kink=a color=yellowOld Dogs#2 : kink=b color=blockNew Dogs#2 : kink=d color=block