Timo Willemsen
Timo Willemsen

Reputation: 8857

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?

Upvotes: 0

Views: 125

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1499760

It makes perfect sense. In the constructor, which is called by clone() with the original collection as an argument, you use:

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. 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:

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

... which will put the elemnts back again. This is horrible though...

Upvotes: 2

icirellik
icirellik

Reputation: 766

You can just implement the Clone method as follows:

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.

Upvotes: 1

Bombe
Bombe

Reputation: 83847

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; assigning to it will change nothing on the outside of the constructor.

Upvotes: 1

Related Questions