Java странное ссылочное поведение? - PullRequest
0 голосов
/ 18 ноября 2011

Допустим, у меня есть следующий код:

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 ]

2 голосов
/ 18 ноября 2011

Это имеет смысл. В конструкторе, который вызывается clone() с исходной коллекцией в качестве аргумента, вы используете:

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

Таким образом, вы удаляете элементов из исходной коллекции при создании новой. Ты не хочешь этого делать ...

Не совсем понятно, как вы можете достичь того, чего хотите, учитывая, что похоже, что ваши CollectionInterface только имеют Add и Remove методы (которые должны быть add и remove следовать соглашениям об именах Java) для работы с элементами - нет способа неразрушающего доступа к коллекции. Это очень странно для типа коллекции. Есть ли какая-либо причина, по которой вы делаете это в первую очередь вместо использования встроенных коллекций?

РЕДАКТИРОВАТЬ: Ах - я только что подумал. В пределах класса у вас есть доступ к внутренним элементам создаваемой коллекции ... так что вы можете разрушительно скопировать элементы из коллекции, которую вы дали, вызвав Remove (как сейчас), но когда вы построите свой массив, вы можете использовать:

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

... что снова вернет elemnts. Это ужасно хотя ...

1 голос
/ 18 ноября 2011

Вы можете просто реализовать метод Clone следующим образом:

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

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

    return rv;
}

Вы можете легко реализовать это в конструкторе, если это необходимо.

1 голос
/ 18 ноября 2011

Вы не можете изменить ссылку на входной параметр, как вы пытаетесь во втором конструкторе.

collection = tempCollection.

а) это синтаксическая ошибка, б) collection является локальной переменной; присвоение ему ничего не изменит снаружи конструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...