程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java的clone實現

java的clone實現

編輯:關於JAVA

理解了實現clone()方法背後的所有細節後,便可創建出能方便復制的類,以便提供了一個本地副本:
 

//: LocalCopy.java
// Creating local copies with clone()
import java.util.*;

class MyObject implements Cloneable {
  int i;
  MyObject(int ii) { i = ii; }
  public Object clone() {
    Object o = null;
    try {
      o = super.clone();
    } catch (CloneNotSupportedException e) {
      System.out.println("MyObject can't clone");
    }
    return o;
  }
  public String toString() {
    return Integer.toString(i);
  }
}

public class LocalCopy {
  static MyObject g(MyObject v) {
    // Passing a handle, modifies outside object:
    v.i++;
    return v;
  }
  static MyObject f(MyObject v) {
    v = (MyObject)v.clone(); // Local copy
    v.i++;
    return v;
  }
  public static void main(String[] args) {
    MyObject a = new MyObject(11);
    MyObject b = g(a);
    // Testing handle equivalence,
    // not object equivalence:
    if(a == b) 
      System.out.println("a == b");
    else 
      System.out.println("a != b");
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    MyObject c = new MyObject(47);
    MyObject d = f(c);
    if(c == d) 
      System.out.println("c == d");
    else 
      System.out.println("c != d");
    System.out.println("c = " + c);
    System.out.println("d = " + d);
  }
} ///:~

不管怎樣,clone()必須能夠訪問,所以必須將其設為public(公共的)。其次,作為clone()的初期行動,應調用clone()的基礎類版本。這裡調用的clone()是Object內部預先定義好的。之所以能調用它,是由於它具有protected(受到保護的)屬性,所以能在衍生的類裡訪問。
Object.clone()會檢查原先的對象有多大,再為新對象騰出足夠多的內存,將所有二進制位從原來的對象復制到新對象。這叫作“按位復制”,而且按一般的想法,這個工作應該是由clone()方法來做的。但在Object.clone()正式開始操作前,首先會檢查一個類是否Cloneable,即是否具有克隆能力——換言之,它是否實現了Cloneable接口。若未實現,Object.clone()就擲出一個CloneNotSupportedException違例,指出我們不能克隆它。因此,我們最好用一個try-catch塊將對super.clone()的調用代碼包圍(或封裝)起來,試圖捕獲一個應當永不出現的違例(因為這裡確實已實現了Cloneable接口)。
在LocalCopy中,兩個方法g()和f()揭示出兩種參數傳遞方法間的差異。其中,g()演示的是按引用傳遞,它會修改外部對象,並返回對那個外部對象的一個引用。而f()是對自變量進行克隆,所以將其分離出來,並讓原來的對象保持獨立。隨後,它繼續做它希望的事情。甚至能返回指向這個新對象的一個句柄,而且不會對原來的對象產生任何副作用。注意下面這個多少有些古怪的語句:
v = (MyObject)v.clone();
它的作用正是創建一個本地副本。為避免被這樣的一個語句搞混淆,記住這種相當奇怪的編碼形式在Java中是完全允許的,因為有一個名字的所有東西實際都是一個句柄。所以句柄v用於克隆一個它所指向的副本,而且最終返回指向基礎類型Object的一個句柄(因為它在Object.clone()中是那樣被定義的),隨後必須將其造型為正確的類型。
在main()中,兩種不同參數傳遞方式的區別在於它們分別測試了一個不同的方法。輸出結果如下:
 

a == b
a = 12
b = 12
c != d
c = 47
d = 48

大家要記住這樣一個事實:Java對“是否等價”的測試並不對所比較對象的內部進行檢查,從而核實它們的值是否相同。==和!=運算符只是簡單地對比句柄的內容。若句柄內的地址相同,就認為句柄指向同樣的對象,所以認為它們是“等價”的。所以運算符真正檢測的是“由於別名問題,句柄是否指向同一個對象?”

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved