由Object類定義的絕大部分方法在本書其他部分讨論。而一個特别值得關注的方法是clone( )。clone( )方法建立調用它的對象的一個複制副本。隻有那些實作Cloneable接口的類能被複制。
Cloneable接口沒有定義成員。它通常用于指明被建立的一個允許對對象進行位複制(也就是對象副本)的類。如果試圖用一個不支援Cloneable接口的類調用clone( )方法,将引發一個CloneNotSupportedExcepti
on異常。當一個副本被建立時,并沒有調用被複制對象的構造函數。副本僅僅是原對象的一個簡單精确的拷貝。
複制是一個具有潛在危險的操作,因為它可能引起不是你所期望的副作用。例如,假如被複制的對象包含了一個稱為obRef的引用變量,當副本建立時,副 本中的obRef如同原對象中的obRef一樣引用相同的對象。如果副本改變了被obRef引用的對象的内容,那麼對應的原對象也将被改變。這裡是另一個 例子。如果一個對象打開一個I/O流并被複制,兩個對象将可操作相同的流。而且,如果其中一個對象關閉了流,而另一個對象仍試圖對I/O流進行寫操作的 話,将導緻錯誤。
由于複制可能引起問題,是以在Object内,clone( )方法被說明為protected。這就意味着它必須或者被由實作Cloneable的類所定義的方法調用,或者必須被那些類顯式重載以便它是公共的。讓我們看關于下面每一種方法的例子。
下面的程式實作Cloneable接口并定義cloneTest( )方法,該方法在Object中調用clone( )方法:
// Demonstrate the clone() method.
class TestClone implements Cloneable {
int a;
double b;
// This method calls Object's clone().
TestClone cloneTest() {
try {
// call clone in Object.
return (TestClone) super.clone();
} catch(CloneNotSupportedException e) {
System.out.println("Cloning not allowed.");
return this;
}
class CloneDemo {
public static void main(String args[]) {
TestClone x1 = new TestClone();
TestClone x2;
x1.a = 10;
x1.b = 20.98;
x2 = x1.cloneTest(); // clone x1
System.out.println("x1: " + x1.a + " " + x1.b);
System.out.println("x2: " + x2.a + " " + x2.b);
這裡,方法cloneTest( )在Object中調用clone( )方法并且傳回結果。注意由clone( )方法傳回的對象必須被強制轉換成它的适當類型(TestClone)。
下面的例子重載clone( )方法以便它能被其類外的程式所調用。為了完成這項功能,它的存取說明符必須是public,如下所示:
// Override the clone() method.
// clone() is now overridden and is public.
public Object clone() {
return super.clone();
class CloneDemo2 {
// here, clone() is called directly.
x2 = (TestClone) x1.clone();
由複制帶來的副作用最初一般是比較難發現的。通常很容易想到的是類在複制時是很安全的,而實際卻不是這樣。一般在沒有一個必須的原因的情況下,對任何類都不應該執行Cloneable。
深複制:将一個對象複制後,不論是基本資料類型還有引用類型,都是重新建立的。簡單來說,就是深複制進行了完全徹底的複制,而淺複制不徹底。
此處,寫一個深淺複制的例子:
public class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private String string;
private SerializableObject obj;
/* 淺複制 */
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
/* 深複制 */
public Object deepClone() throws IOException, ClassNotFoundException {
/* 寫入目前對象的二進制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 讀出二進制流産生的新對象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
public String getString() {
return string;
public void setString(String string) {
this.string = string;
public SerializableObject getObj() {
return obj;
public void setObj(SerializableObject obj) {
this.obj = obj;
}
class SerializableObject implements Serializable {
要實作深複制,需要采用流的形式讀入目前對象的二進制輸入,再寫出二進制資料對應的對象。
本文轉自 一點點征服 部落格園部落格,原文連結:http://www.cnblogs.com/ldq2016/p/5231832.html,如需轉載請自行聯系原作者