Java奇怪的引用行为?

时间:2011-11-17 21:22:54

标签: java reference

假设我有以下代码:

public class Collection implements CollectionInterface{

 ElementInterface[] elementArray = new ElementInterface[100];
 int amountOfElements = 0;

 public Collection()
 {

 }

 public Collection(CollectionInterface collection)
 {
  CollectionInterface tempCollection = new Collection();
  while(!collection.isEmpty())
  {
   ElementInterface element = collection.Remove().clone();
   tempCollection.Add(element.clone2());
   elementArray[amountOfElements++] = element;
  }
  collection = tempCollection;

 }

 public void Add(ElementInterface element){
     elementArray[amountOfElements++] = element;
 }

 public ElementInterface Remove(){
  ElementInterface element = elementArray[amountOfElements].clone2();
  elementArray[amountOfElements] = null;
  amountOfElements--;
  return element;
 }

 public boolean isEmpty(){
  return amountOfElements == 0;
 }

 public CollectionInterface clone()
 {
  return new Collection(this);
 }
}
好吧,它看起来有点奇怪,而且确实如此。但是,如果我使用以下代码:

CollectionInterface collection = new Collection();
collection.Add(new Element("Foo"));
collection.Add(new Element("Bar"));
CollectionInterface collection2 = collection.clone();

第一个不再包含任何元素。怎么可能?

3 个答案:

答案 0 :(得分:2)

这很有道理。在构造函数中,clone()以原始集合作为参数调用,使用:

ElementInterface element = collection.Remove().clone();

因此,您在创建新元素时从原始集合中删除元素。你不想这样做......

鉴于您的CollectionInterface 具有AddRemove方法,应该达到您想要的效果并不是很清楚是addremove遵循Java命名约定来处理元素 - 无法以非破坏性方式访问集合。对于集合类型,非常奇数。您是否有任何理由首先这样做而不是使用内置集合?

编辑:啊 - 我刚才有一个想法。 类中,您可以访问正在构建的集合的内部...这样您就可以破坏性地复制中的元素通过调用给出的集合Remove(就像你现在一样)但是当你构建了数组时,可以使用:

for (int i = 0; i < amountOfElements; i++)
{
    collection.Add(elementArray[i].clone2());
}

......这将使元素重新回归。这是可怕的虽然......

答案 1 :(得分:1)

在第二个构造函数中尝试时,无法更改输入参数的引用。

collection = tempCollection.

a)这是一个语法错误, b)collection是一个局部变量;分配给它将不会改变构造函数的外部。

答案 2 :(得分:1)

您可以按如下方式实现Clone方法:

public Object Clone() {
    Collection rv = new Collection();

    for (ElementInterface element : elementArray) {
        rv.Add(element.clone());
    }

    return rv;
}

如果需要,您可以在构造函数中轻松实现它。