简体   繁体   English

Java奇怪的参考行为?

[英]Java strange reference behaviour?

Lets say I have the following code: 可以说我有以下代码:

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

Allright, it might seem a bit strange, and it is. 好吧,看起来似乎有些奇怪,确实如此。 But if I use the following code: 但是,如果我使用以下代码:

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

The first one doesn't contain any elements anymore. 第一个不再包含任何元素。 How is that possible? 那怎么可能?

It makes perfect sense. 这是很合理的。 In the constructor, which is called by clone() with the original collection as an argument, you use: 在由clone()以原始集合作为参数调用的构造函数中,您可以使用:

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

So you're removing elements from the original collection as you create the new one. 因此,在创建新集合时,您将从原始集合中删除元素。 You don't want to do that... 你不想那样做...

It's not really clear how you can achieve what you want, given that it looks like your CollectionInterface only has Add and Remove methods (which should be add and remove to follow Java naming conventions) to deal with elements - no way of accessing the collection non-destructively. 这不是真的清楚如何才能达到你想要的东西,因为它看起来像你的CollectionInterface 只有已经AddRemove方法(应该addremove遵循Java的命名约定)来处理元素-没有访问该集合非的方式-destructively。 That's very odd for a collection type. 对于集合类型来说这奇怪。 Is there any reason you're doing this in the first place instead of using the built-in collections? 首先,有什么理由要使用内置集合吗?

EDIT: Ah - I've just had a thought. 编辑:啊-我刚刚有一个想法。 Within the class, you have access to the internals of the collection you're building... so you can destructively copy the elements from the collection you're given by calling Remove (as you are now) but then when you've built your array, you can use: 该类中,您可以访问要构建的集合的内部信息...因此,您可以通过调用Remove (从现在开始)以破坏性的方式给定的集合中复制元素但是在构建完成后您的数组,可以使用:

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

... which will put the elemnts back again. ……这将再次让妖精们回来。 This is horrible though... 虽然这太可怕了...

You can not change the reference of an input parameter, as you try in the second constructor. 您无法更改输入参数的引用,就像在第二个构造函数中尝试的那样。

collection = tempCollection.

a) is this a syntax error, b) collection is a local variable; a)这是语法错误吗?b) collection是局部变量; assigning to it will change nothing on the outside of the constructor. 分配给它不会对构造函数造成任何影响。

You can just implement the Clone method as follows: 您可以按如下方式实现Clone方法:

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

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

    return rv;
}

You could easily implement this in the constructor if necessary. 如有必要,您可以在构造函数中轻松实现此目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM