2013-08-29 5 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 클래스의 새 인스턴스를 만드는 것이 좋습니다. 그렇게 할 수 있다고 생각하지만 객체를 복제하는 방법에 대해 알고 싶습니다.

이 작업을 수행하는 방법을 알고있는 유일한 방법은이 개체를 복제하는 것입니다. 이거 안전한가요? 재정의 된 메소드 add (MATIdentifier)와 contains (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에 등호 작업을 무시하거나 사용자 정의를 작성하는 것보다 MATIdentifier Comparator를 만드는 중 아마 더 좋은 습관이다 : 다음은 당신의 가정이 정확한지 확인하기 위해이 프레임 워크를 사용하는 방법의 예입니다 Vector에 impl을 포함하고 추가합니다. java.util.Set을 사용하는 것이 좋습니다. 또한 중요한 기능은 테스트하기가 더 어렵 기 때문에 좋은 기능은 아닙니다. 특수화 된 Vector 구현을 계속하기를 원한다면 클래스로 옮겨야합니다.

+0

Java Set을 사용하는 것과는 대조적으로, 사용자 (또는 프로그래머)가 Vector에 MATIdentifier가 아닌 유형이 있는지 확인하려고했는지 알 수있을 것입니다. 형식이 MATIdentifier가 아닌 경우 contains 메서드에 인쇄 또는 로깅 문을 넣을 수 있습니다. –

+0

또한 말했듯이 적어도 java.util.Set에서 equals (Object)를 재정의해야합니다. Set에서 override equals를 추측하는 것은 내 Vector 서브 클래스에서 원하는대로 원하는 기능을 포함하도록 설정합니다. 그래서 내 Set 서브 클래스를 다른 클래스에 두거나, 내부 클래스로 두어야합니다. 맞습니까? –

+0

메모 : http://smallwig.blogspot.com/2007/12/why-does-setcontains-take-object-not-e.html –