要點
1> 為了獲取對象的一份拷貝,我們可以利用Object類的clone()方法。
2> 在派生類中覆蓋基類的clone(),並聲明為public。
3> 在派生類的clone()方法中,調用super.clone()。
4> 在派生類中實現Cloneable接口。
5>Cloneable是一個沒有抽象方法的標識接口。
建立一個本地拷貝
給一個對象建立本地拷貝的原因很可能是由於您計畫修改該對象,並且您不想修改方法調用者的對象。假如您確定您需要一個本地拷貝,您能夠使用Object類的clone()方法來執行這項操作。clone()方法被定義為受保護方法,但您必須在您希望克隆的任何子類中重新公開定義他。
例如,標準庫類ArrayList忽略clone(),但您能夠這樣為ArrayList調用clone()方法:
import java.util.*;class MyInt {
private int i;
public MyInt(int ii) { i = ii; }
public void increment() { i++; }
public String toString() {
return Integer.toString(i);
}
}public class Test {
public static void main(String[] args) {
ArrayList al = new ArrayList();
for(int i = 0; i < 10; i++ )
al.add(new MyInt(i));
ArrayList al1 = (ArrayList)al.clone();
// Increment all al1's elements:
for(Iterator e = al1.iterator(); e.hasNext(); )
((MyInt)e.next()).increment();}
}
clone()方法生成一個Object,他必須重新轉變為適當的類型。這個例子說明ArrayList的clone()方法如何不能自動克隆ArrayList包含的每一個對象——原有ArrayList和克隆後的ArrayList是相同對象的別名。
這種情況通常叫做淺拷貝,因為他僅僅複製一個對象的“表面”部分。實際的對象由這個“表面”,引用指向的任何對象,連同那些對象指向的任何對象等構成。這往往被稱作“對象網路”。假如您拷貝任何這些內容,則被稱為深拷貝。例如:
class DeeplyClone
{
public static void main(String[] args)
{
Professor p=new Professor("feiyang",23);
Student s1=new Student("zhangshan",18,p);
Student s2=(Student)s1.clone();
s2.p. name="Bill.Gates";
s2.p.age=30;
System.out.println("name="+s1.p. name+","+"age="+s1.p.age);
}
}
class Professor implements Cloneable
{
String name;
int age;
Professor(String name,int age)
{
this. name=name;
this.age=age;
}
public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
e.printStackTrace();
}
return o;
}
}
class Student implements Cloneable
{
Professor p;
String name;
int age;
Student(String name, int age,Professor p)
{
this. name=name;
this.age=age;
this.p=p;
}
public Object clone()
{
//Object o=null;
Student o=null;
try
{
o=(Student)super.clone();
}
catch(CloneNotSupportedException e)
{
e.printStackTrace();
}
return o;
}
}
例外
如果為一個不實現cloneable的類調用clone的話,那么就會拋出一個CloneNotSupportedException異常。相對於實現cloneable接口的類來說,如果為使用默認方法Object.clone的類的實例調用clone的話,就必須採取以下動作之一:
1.在clone的調用周圍包裝一個try代碼塊並捕捉到CloneNotSupportedException異常。
2.將異常CloneNotSupportedException添加到調用clone的方法的throws子句中,拋出這個異常。