2013-08-29 60 views
0

我有這樣的載體,其我定義爲實例變量,也可以作爲一個內部類克隆一個目的是通過內部類定義

private Vector<MATIdentifier> matIds = new Vector<MATIdentifier>(){ 

    @Override 
    public boolean add(MATIdentifier mi){ 


    if(this.contains(mi)){ 

      return false; 

      } 
     super.add(mi); 
     return true; 

} 

    @Override 
    public boolean contains(Object o){ 

     if(o instanceof MATIdentifier){ 


      for(MATIdentifier mi: this){ 

       if(mi.getIdValue().equals(((MATIdentifier)o).getIdValue())){ 

       return true; 

       } 
      } 
     } 
       return false; 

     } 

}; 

後來在節目中,我要填充這個向量來自數據庫。最好創建這個Vector類的新實例,而不是簡單地刪除所有元素並重用相同的對象 - 我想我可以這樣做,但我仍然想知道如何克隆該對象。

我知道如何做到這一點的唯一方法就是clone()這個對象。這安全嗎?它會克隆重寫的方法添加(MATIdentifier)幷包含(Object)?

也許我應該重寫clone()也......?或者Vector中的預定義clone()方法是否足夠?

注意:我把@Override註釋放在自己的位置,Java編譯器(Eclipse)沒有讓我那麼做。

回答

2

這個問題涉及Java中的幾個概念。首先,我想問爲什麼,如果你想保證唯一性,你不使用java.util.Set

接下來,克隆方法。原始數據結構的克隆是shallow copy還是deep copy?如果我們看Vector API documentation from Oracle,它告訴我們:

返回這個向量的克隆。該副本將包含對內部數據陣列的 克隆的引用,而不是對該Vector對象的原始內部數據數組的引用。

因此,我們可以從這個那個,首先,它也克隆內部數據學習,所以這表明深副本。現在,它是否也複製重寫的方法?對此的快速測試告訴我,是的,它確實如此。

最後,如何測試這個?我建議你使用像junit這樣的單元測試框架。 以下是如何使用這個框架,以確保你的假設是正確的一個例子:

package test.good; 

import static org.junit.Assert.*; 

import java.util.Vector; 

import org.junit.Before; 
import org.junit.Test; 

public class CloneTest { 

    private Vector<MATIdentifier> matIds; 

    MATIdentifier id1 = new MATIdentifier("first"); 
    MATIdentifier id2 = new MATIdentifier("second"); 
    MATIdentifier id3 = new MATIdentifier("third"); 
    MATIdentifier idDuplicate = new MATIdentifier("first"); 

    @Before 
    public void prepare() { 
     matIds = new Vector<MATIdentifier>() { 
      @Override 
      public boolean add(MATIdentifier mi) { 
       if (this.contains(mi)) { 
        return false; 
       } 
       super.add(mi); 
       return true; 
      } 

      @Override 
      public boolean contains(Object o) { 
       if (o instanceof MATIdentifier) { 
        for (MATIdentifier mi : this) { 
         if (mi.getIdValue().equals(((MATIdentifier) o).getIdValue())) { 
          return true; 
         } 
        } 
       } 
       return false; 
      } 
     }; 
    } 

    private void populateVector(Vector<MATIdentifier> vector) { 
     vector.add(id1); 
     vector.add(id2); 
     vector.add(id3); 
    } 

    /** 
    * Tests that adding new values returns true, and adding duplicates returns 
    * false, and that the duplicates are not actually added 
    */ 
    @Test 
    public void testDuplicateFails() { 
     boolean added; 
     added = matIds.add(id1); 
     assertTrue(added); 
     added = matIds.add(id2); 
     assertTrue(added); 
     added = matIds.add(idDuplicate); 
     assertFalse(added); 
     assertEquals(2, matIds.size()); 
    } 

    @Test 
    public void testDeepCopy() { 
     // Start with by pupulating our customized vector 
     populateVector(matIds); 
     assertEquals(3, matIds.size()); 
     // Clone the vector 
     Vector<MATIdentifier> clone = (Vector<MATIdentifier>) matIds.clone(); 
     assertEquals(3, clone.size()); 
     // remove something from the original 
     matIds.remove(2); 
     assertEquals(3, clone.size()); 
     assertEquals(2, matIds.size()); 
     // add something to the original 
     matIds.add(new MATIdentifier("New Value")); 
     assertEquals(3, clone.size()); 
     assertEquals(3, matIds.size()); 
     // add a duplicate to the clone, to ensure that the overridden behavior 
     // is present in the clone 
     boolean added = clone.add(id1); 
     assertFalse(added); 

    } 

} 

class MATIdentifier { 
    private String idValue; 

    public MATIdentifier(String idValue) { 
     this.idValue = idValue; 
    } 

    public String getIdValue() { 
     return idValue; 
    } 

    public void setIdValue(String idValue) { 
     this.idValue = idValue; 
    } 

} 

PS,它可能是更好的做法,要麼覆蓋上MATIdentifier equals操作或創建一個MATIdentifier Comparator比創建一個自定義包含併爲您的Vector添加impl。我真的建議你使用java.util.Set。 此外,創建這樣的匿名內部類型與我所假設的是重要的功能不是一個好的做法,因爲它使您的代碼更難以測試。如果你堅持繼續使用專門的Vector實現,你應該將它移到一個類中。

+0

與使用Java Set相反,這種方式我相信我會知道用戶(或我是程序員)是否試圖檢查Vector是否包含不是MATIdentifier的類型。如果類型不是MATIdentifier,我可以在contains方法中放置打印或日誌記錄語句。 –

+0

也如您所說,我必須至少覆蓋java.util.Set中的equals(Object)。我猜測在Set中重載equals會給Set所需的包含功能 - 正如我在Vector子類中所需要的那樣。所以我必須將我的Set子類放入不同的類中,或者作爲內部類,對嗎? –

+0

也注意到這一點:http://smallwig.blogspot.com/2007/12/why-does-setcontains-take-object-not-e.html –