例:
Friend.java
class Friend implements Cloneable {
int age;
String name;// StringBuffer name;
public Friend(int age, String name) {
this.age = age;
this.name = name;
}
public Object clone () throws CloneNotSupportedException {
return super.clone();
}
}
Person.java
class Person implements Cloneable {
int age;
/* *
*String 類型特殊,因?yàn)樗麨橐眯停宜赶虻闹禐槌A浚寺〕鰜淼膶ο蟾淖兯闹?br />
*實(shí)際上是改變了克隆出來對象String類型成員的指向,不會影響被克隆對象的值及其指向。
*/
String name;
Friend f;
public Person(int age, String name, Friend f) {
this.age = age;
this.name = name;
this.f = f;
}
//組合對象的克隆
public Object clone () throws CloneNotSupportedException {
Person p = (Person)super.clone(); //需要對每一個(gè)成員對象實(shí)現(xiàn)clone()
p.f = (Friend)p.f.clone();
return p;
}
public String toString(){
StringBuffer sb = new StringBuffer();
return super.toString()+sb.append(" age=").append(age).
append(",name=").append(name).
append(" friend=").append("f.name=").
append(f.name).append("f.age=").append(f.age).toString();
}
}
CloneTest.java
import java.util.ArrayList;
import java.util.Iterator;
public class CloneTest {
public static void main(String [] args) throws CloneNotSupportedException {
Person p = new Person(4,"num1",new Friend(5,"haha"));//new StringBuffer("haha")));
Person p1 = (Person)p.clone();
p1.name = "new"; //看似類似于基本類型,其實(shí)暗藏玄機(jī)
p1.age = 10;
p1.f.name = "hehe";
//p1.f.name = new StringBuffer("hehe");//新產(chǎn)生了一個(gè)引用,覆給了它
p1.f.age = 56;
System.out.println (p);//+"—— age"+p.age +" name "+p.name );
System.out.println (p1);//+"—— age"+p1.age +" name "+p1.name );
ArrayList testList=new ArrayList();
testList.add(p);
testList.add(p1);
System.out.println("befor testList:"+testList);
//ArrayList的克隆
ArrayList newList=(ArrayList)testList.clone();
//要一一走訪ArrayList/HashMap所指的每一個(gè)對象,并逐一克隆。
for(int i=0; i<newList.size() ; i++)
newList.set(i, ((Person)newList.get(i)).clone());
for(Iterator e=newList.iterator();e.hasNext();)
((Person)e.next()).age+=1;
System.out.println("after: testList"+testList);
System.out.println("after: newList"+newList);
}
}
總結(jié)
1、基本數(shù)據(jù)類型能自動實(shí)現(xiàn)深度clone。
2、String是一個(gè)例外。
但對于我們編程來說可以和操作基本數(shù)據(jù)類型一樣做,基本沒影響。大大方便了我們的編程。
String類型的變量clone后的表現(xiàn)好象也實(shí)現(xiàn)了深度clone,但其實(shí)只是一個(gè)假象。
因?yàn)閳?zhí)行 p1.name = "new";語句時(shí),它作用相當(dāng)于生成了一個(gè)新的string類型,然后又賦回給p1.name。
這是因?yàn)閟tring被sun公司的工程師寫成了一個(gè)不可更改的類(immutable class),在所有string類中的函數(shù)都不能更改自身的值。
==> 這告訴我們支持更方便實(shí)現(xiàn)克隆的一種途徑:將自己定義的類編寫為不可更改。
3、StringBuffer需要做特殊處理String和StringBuffer有區(qū)別。
可以借鑒類似技巧對StringBuffer型的變量實(shí)現(xiàn)克隆效果:sb=new StringBuffer(sb.toString());