2009-07-06 136 views
10

有沒有人有任何建議或建立的最佳做法和命名約定在Java複製構造函數/工廠方法等?特別是說,我有一個類Thing,我想要一個方法返回一個新的Thing與傳入的Thing相同的值(或作爲實例,如果它是一個實例方法)。你會有這個作爲構造函數或靜態工廠方法或實例方法嗎?你會怎麼稱呼它?如果你不用Java進行克隆,那麼你做什麼,你叫什麼?

根據標題,我想避免clone()Cloneable

+0

爲什麼你想避免的clone()和Cloneable的? – 2009-07-06 15:15:59

回答

3

我會稱之爲複製方法或複製構造函數(視情況而定)。如果這是一種靜態方法,那麼我會稱之爲工廠。

在做什麼方面,最靈活和最長壽的選項是複製構造函數。這使得子類能夠像父母一樣複製自己。

2

我會做一個構造

... 
public Thing(Thing copyFrom) 
{ 
    attr1 = copyFrom.attr1; 
    attr2 = copyFrom.attr2; 
    //etc... 
} 

那麼當你想克隆它

Thing copy = new Thing(copy from me); 
0

你有幾個選擇,實施Cloneable,添加一個拷貝構造函數,但我的首選方式是使用一個名稱描述複製操作正在進行的方法(靜態還是實例) - 是深層還是淺層複製等。

15

有效的Java推薦門茲以下任一操作:

  1. 一個拷貝構造函數(如由他人注意):

    公共項目(項目項)

  2. 副本工廠方法:

    公共靜態項目newInstance(Item item)

(另外,不可複製的不可變項)

主要區別在於#1選擇結果的實際類,#2實現者可以返回子類。這門課的語義可以指導你將哪一門課最好。

0

使用immutable data structures。你覺得你需要clone()的唯一原因是你正在改變你的對象。別那樣做。想想你可以如何:

  • 讓你的課最終。
  • 在您的課程中最終和私人領域。

例如,這裏有一個「二傳手」的一個不變的三維矢量對象:

public Vector3D setX(double x) { 
    return new Vector3D(x, this.y, this.z); 
} 

所以我想我說的是我對使用拷貝構造函數,而不是突變,和我只是根據我想修改的屬性命名它們。

0

另一種選擇是實現在對象的複製方法,例如:

interface Has3DCoords { 
    void setLocation(double x, double y, double z); 

    void copyCoordsTo(Has3DCoords dest); 
} 

你會然後實現複印用一塊代碼等:

class Thing implements Has3DCoords { 
    private Point3D loc; 
    // ... 

    void setLocation(double x, double y, double z) { 
     loc.setLocation(x, y, z); 
     // or: loc = new Point3D(x, y, z); 
    } 

    void copyCoordsTo(Has3DCoords dest) { 
     loc.copyCoordsTo(dest); 
     // or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ()); 
    } 

    OtherThing createOtherThing() { 
     OtherThing result = new OtherThing(); 
     this.copyCoordsTo(result); 
     return result; 
    } 
} 

這可以是有用如果:

  • 克隆整個對象沒有意義
  • 有那些經常被複製爲一個單元的一組相關屬性
  • 你不想暴露locThing
  • 屬性的數量是很大的屬性(或者有很多這樣的羣體),所以要求所有這些參數的構造函數都很笨拙。
0

這不是複製對象的最好方法,但如果你希望一個序列化對象的執行深拷貝以下有時是有用的。這避免了必須編寫複製構造函數,實現Cloneable或編寫工廠類。

ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(bos); 

//Serializes the input object 
oos.writeObject(input); 

ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); 
ObjectInputStream ois = new ObjectInputStream(bais); 

//Copy of the input object 
Object output = ois.readObject(); 

不要忘記處理異常並很好地關閉流。