1

我有这个向量,我定义为一个实例变量,也定义为一个内部类

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() 这个对象。这安全吗?它会克隆覆盖的方法 add(MATIdentifier) 和 contains(Object) 吗?

也许我也应该覆盖 clone() ......?或者 Vector 中预定义的 clone() 方法是否足够?

注意:我将@Override 注释放在自己身上,Java 编译器 (Eclipse) 出于某种原因没有让我这样做。

4

1 回答 1

3

这个问题涉及Java中的几个概念。

首先,我想问一下,如果要保证唯一性,为什么不使用java.util.Set

接下来,克隆方法。克隆是原始数据结构的浅拷贝还是深拷贝?如果我们查看Oracle 的 Vector API 文档,它会告诉我们:

返回此向量的克隆。该副本将包含对内部数据数组的克隆的引用,而不是对该 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 实现,则应将其移至类中。

于 2013-08-29T15:57:39.317 回答