簡體   English   中英

在Java中實現Clone還有其他選擇嗎?

[英]Are there any alternatives to implementing Clone in Java?

在我的Java項目中,我有一個各種類型的交易者的向量。 這些不同類型的交易者是Trader類的子類。 現在,我有一個方法,將Trader作為參數,並在向量中存儲50次左右。 我遇到了問題,因為存儲相同的對象50次只是存儲相同對象的50個引用 我需要存儲50 對象的副本 我已經研究過如何實現Clone ,但是我不希望定義一種Trader的程序員不必擔心讓他們的類可以克隆 此外,正如本頁所指出的,實現克隆會產生各種問題。 我認為復制構造函數不會起作用,因為如果我在Trader類中定義了一個,它就不會知道它正在復制的Trader的類型,只是制作一個通用的Trader。 我能做什么?

編輯:我真的不想制作某個特定對象的精確副本。 我真正想要做的是在向量中添加一定數量的交易者。 問題是用戶需要在參數中指定他想要添加的交易者類型。 這是我想要做的一個例子:(雖然我的語法完全是虛構的)

public void addTraders(*traderType*)
{
    tradervect.add(new *traderType*())
}

我怎樣才能在Java中實現這樣的目標?

只需添加一個抽象的復制方法。 您可以使用協變返回類型,以便指定派生類型以返回派生實例,這可能重要也可能不重要。

public interface Trader {
    Trader copyTrader();
    ...
}


public final class MyTrader implements Trader {
    MyTrader copyTrader() {
        return new MyTrader(this);
    }
    ...
}

有時您可能希望一般性地處理需要克隆然后返回正確類型集合的派生類型的Trader集合。 為此,您可以以慣用的方式使用泛型:

public interface Trader<THIS extends Trader> {
    THIS copyTrader();
    ...
}


public final class MyTrader implements Trader<MyTrader> {
    public MyTrader copyTrader() {
        return new MyTrader(this);
    }
    ...
}

我有點不清楚你為什么要存儲同一個對象的50個左右的克隆,除非他們原來的交易者作為后期交易者的原型(見模式)。

如果要制作對象的精確副本,則必須考慮多態性問題。 如果允許子類化給定類的人員添加狀態成員,那么你已經對equals和compareTo等函數感到頭疼了,那個克隆就是另外一個需要特殊處理的情況。

我不同意克隆總是邪惡的,有時是必要的。 但是,在子類化的情況下,很多事情變得棘手。

我建議你閱讀(當你有機會時)Bloch的“Effective Java”,它涵蓋了很多他的主題。 Bracha的觀點是,讓別人擴展你的課程並不是一個好主意,如果你這樣做,你需要很好地記錄他們必須做的事情,並希望他們遵循你的指示。 真的沒有辦法繞過那個。 您可能還想讓您的交易者不可變。

正常地執行一個實現Clone,並在類頭中清楚地指出任何從您的Trader繼承並添加狀態成員的人必須實現X方法(指定哪個)。

找到繞過實際Cloneable並仍然克隆的技巧不會克服繼承問題。 這里沒有銀彈。

一個選項:如果可以使對象可序列化,則可以序列化然后反序列化它以創建副本,類似於通過RMI傳遞對象時發生的情況。

快速復制方法:

public MyObject copy() {
    ObjectOutputStream oos = null;
    ObjectInputStream ois = null;
    try {
        ByteArrayOutputStream bos =  new ByteArrayOutputStream();
        oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        oos.flush();
        ByteArrayInputStream bin =
            new ByteArrayInputStream(bos.toByteArray());
        ois = new ObjectInputStream(bin);
        return (MyObject)ois.readObject();
    } catch(Exception e) {
        return null;
    } finally {
        try {
            oos.close();
            ois.close();
        } catch (Exception e) {
            return null;
        }
    }
}

Uri是對的,與州的多態性開辟了一大堆蠕蟲。

我認為繼承Cloneable並覆蓋clone()可能是最簡單的方法。 我相信你可以使返回類型協變。

一種方法是使它成為像Java自己的String這樣的最終類,它將對類Trader的對象進行任何更改以在內存中創建新副本,但是它將無法對其進行子類化。

另一種(更好的)方法是使用工廠方法來創建和復制Trader對象,這意味着您不能允許使用默認構造函數,即將其設為私有。 這樣您就可以控制類具有的實例數。 http://en.wikipedia.org/wiki/Factory_method

public class Trader {

    /* prevent constructor so new cant be used outside the factory method */
    private Trader() {
    }

    /* the factory method */
    public static Trader createTrader(int whatKindOfTrader) {

        switch (whatKindOfTrader) {
        case 0:
            return new Trader1(); // extends Trader
        case 1:
        default:
            return new Trader2(); // extends Trader
        }
        return new Trader3(); // or throw exception
    }
}

您甚至可以指定另一個重載方法,或者第二個參數,它接受一個Trader並將其復制到一個新的,從而替換clone。 順便說一下,您可能希望覆蓋clone()方法並拋出CloneNotSupportedException,以防止默認的Object克隆。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM