簡體   English   中英

在LinkedList上實現克隆

[英]Implementing clone on a LinkedList

我試圖在DoubleLinkedList上實現clone()方法。 現在,問題是通過“約定”實現它比創建一個新的DoubleLinkedList並用我當前的DoubleLinkedList的所有元素填充它要麻煩得多。

這樣做有什么不方便嗎?

這是我目前的做法:

@Override
public DoubleLinkedList<T> clone() {
    DoubleLinkedList<T> dll = new DoubleLinkedList<T>();

    for (T element : dll) {
        dll.add(element);
    }

    return dll;
}

以下是大會的內容:

@Override
public DoubleLinkedList<T> clone() {
    try {
        DoubleLinkedList<T> dll = (DoubleLinkedList<T>)super.clone();
        //kinda complex code to copy elements
        return dll;
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e.toString());
    }
}

正如您正確指出的那樣,約定是在clone()的實現開始時始終調用super.clone() clone() Object#clone()API文檔

按照慣例,返回的對象應該通過調用super.clone來獲得。 如果一個類及其所有超類(Object除外)遵循這個約定,那么x.clone()。getClass()== x.getClass()就是這種情況。

您的第一次嘗試(不使用super.clone() )具有以下問題:

假設我有

class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable

(並且IntDoubleLinkedList不打擾覆蓋clone() )並運行以下代碼:

IntDoubleLinkedList idll = new IntDoubleLinkedList();
IntDoubleLinkedList idll2 = (IntDoubleLinkedList) idll.clone();

會發生什么? 的克隆方法DoubleLinkedList將被執行,其中,如果不經過super.clone()來返回的實例DoubleLinkedList這反過來又可以不被鑄造成IntDoubleLinkedList ClassCastException

那么super.clone()如何解決這個問題呢? 好吧,如果每個人都堅持在重寫克隆方法中調用super.clone()的約定,最終將調用Object.clone() ,並且此實現將創建一個正確類型的實例(在本例中為IntDoubleLinkedList )!

正如其他人所解釋的那樣,如果你要覆蓋clone你應該遵守它的合同。

如果你喜歡你目前擁有的方式,只是讓DoubleLinkedListCloneable ,把你的實現成為一個拷貝構造函數或靜態工廠方法。 靜態工廠方法還具有為泛型類型參數提供一些類型推理的額外好處。

PS LinkedList 一個雙向鏈表。

如果您通過創建新列表並添加源中的所有元素來執行此操作,那么如果您執行以下操作:

DoubleLinkedList<Foo> l1 = new DoubleLinkedList<Foo>();
l1.add (new Foo(params));
DoubleLinkedList<Foo> l2 = l1.clone();
Foo foo = l2.get(0);
foo.setProperty("new Value");

foo.property將在兩個列表中都是“新值”(反過來相同;如果在l1中更改它,則更改將出現在l2中)。 正確的方法是實際克隆每個元素並添加克隆以確保列表是獨立的。 請注意,只有在更改元素的屬性時才會發生這種情況,而不是在列表中添加,移動和刪除元素時。

編輯:剛才意識到,由於它是一個鏈表,下一個/前一個元素是元素的屬性,所以即使添加,刪除也會影響這兩個列表。

“約定”調用super.clone()是為了確保克隆對象的最終類型與正在克隆的對象匹配。 例如,如果你在clone()方法中實例化你自己的新DoubleLinkedList ,那么現在很好,但是后來如果一個子類無法覆蓋clone() ,它將最終返回一個DoubleLinkedList而不是它自己的類的克隆。 (它也可能無法克隆其附加字段,如果有的話,可能!所以存在更大的問題。)

從這個意義上說,傳統的方法是優選的,它確實很笨重。

但是,這兩種實現都存在類似的問題:您沒有深度復制數據結構。 克隆只是一個淺警察。 這可能不是調用者所期望的。 您需要遍歷並使用值的克隆替換DoubleLinkedList每個值,對於其他非原始字段也是如此。

從這個意義上說,傳統方法會在這里給出錯誤的結果! 你需要第三種方式。 你的第一種方法可能只是工作,除了你需要添加element.clone()

暫無
暫無

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

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