2011-11-17 75 views
0

可以说我有下面的代码:Java奇怪的引用行为?

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(); 

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

+0

如果你真的认为是Java,就不要说JavaScript(它们没有任何共同之处)。 – helpermethod

+3

...请给*真正的*代码,而不是代码,这相当明显不会编译。 –

+0

我说JavaScript吗?我不是故意的?也许autocompletion做到了?我不确定,对不起。还有Upvoted Jon Skeet,你是​​绝对正确的。我正在编辑它,但你太快了! –

回答

1

您不能在第二个构造函数中尝试更改输入参数的引用。

collection = tempCollection. 

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

+0

这不是给我一个语法错误。所以你不能改变构造函数的参数引用? –

+0

其实这是我的问题。当然这不行! –

+0

然后接受我的回答将是适当的行为,我猜。 :) – Bombe

2

它非常有意义。在构造函数中,这是由clone()与原来的集合称为作为参数,可以使用:

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

所以你去除原始集合元素创建新的。你不想这样做...

这不是真的清楚如何才能达到你想要的东西,因为它看起来像你的CollectionInterface只有AddRemove方法(这应该是addremove到遵循Java命名约定)来处理元素 - 无法以非破坏性的方式访问集合。这是非常奇怪的集合类型。你有没有任何理由,而不是使用内置集合呢?

编辑:啊 - 我刚刚有一个想法。 范围内,您可以访问您正在构建的集合的内部...因此,您可以通过调用Remove(如您现在)来破坏性地复制要从收集的集合中的元素,你已经建立了你的阵列,你可以使用:

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

......这将把元素放回去。这是可怕的尽管...

+0

这实际上并非整个交易。他试图使用构造函数参数作为返回值。 – Bombe

+0

@Bombe:你不明白你的意思。我看不到你在描述什么...... –

+0

他将给定集合中的元素移动到临时集合中,同时克隆它们(在进程中克隆它们两次),并在构造函数结束时尝试将临时集合分配回原始集合。 – Bombe

1

你可以只实现Clone方法如下:

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

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

    return rv; 
} 

如有必要,你可以很容易地实现这个构造函数。