ArrayList объекта, с циклом, печать дубликатов [дубликат]

Объявлено, но не определено переменная или функция.

Типичным объявлением переменной является

extern int x;

. Поскольку это только объявление, требуется одно определение. Соответствующим определением будет:

int x;

Например, следующее генерирует ошибку:

extern int x;
int main()
{
    x = 0;
}
//int x; // uncomment this line for successful definition

Аналогичные замечания относятся к функциям. Объявление функции без ее определения приводит к ошибке:

void foo(); // declaration only
int main()
{
   foo();
}
//void foo() {} //uncomment this line for successful definition

Будьте осторожны, чтобы выполняемая вами функция точно соответствовала той, которую вы объявили. Например, у вас могут быть несогласованные cv-квалификаторы:

void foo(int& x);
int main()
{
   int x;
   foo(x);
}
void foo(const int& x) {} //different function, doesn't provide a definition
                          //for void foo(int& x)

Другие примеры несоответствий включают

  • Функция / переменная, объявленная в одном пространстве имен, определенное в другом.
  • Функция / переменная, объявленная как член класса, определяемая как глобальная (или наоборот).
  • Тип возвращаемого значения функции, номер и типы параметров и соглашение о вызове не совсем точно согласуются.

Сообщение об ошибке из компилятора часто дает вам полное объявление переменной или функции, которая была объявлена, но не определена. Сравните его с определением, которое вы указали. Убедитесь, что каждая деталь соответствует.

62
задан Duncan Jones 9 November 2013 в 09:34
поделиться

4 ответа

Эта проблема имеет две типичные причины:

  • Статические поля, используемые объектами, которые вы сохранили в списке
  • Случайно добавив тот же объект в список

Статические поля

Если объекты в вашем списке хранят данные в статических полях, каждый объект в вашем списке будет казаться одним и тем же, поскольку они удерживают одинаковые значения. Рассмотрим следующий класс:

public class Foo {
  private static int value; 
  //      ^^^^^^------------ - Here's the problem!

  public Foo(int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }
}

В этом примере есть только один int value, который разделяется между всеми экземплярами Foo, поскольку он объявлен static. (См. учебник «Знакомство с членами класса» .)

Если вы добавите несколько объектов Foo в список, используя приведенный ниже код, каждый экземпляр вернет 3 из вызова to getValue():

for (int i = 0; i < 4; i++) {      
  list.add(new Foo(i));
}

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

Добавление одного и того же объекта

Если вы добавите временную переменную в список, вы должны создать новый экземпляр каждый раз, когда вы выполняете цикл. Рассмотрим следующий ошибочный фрагмент кода:

List<Foo> list = new ArrayList<Foo>();    
Foo tmp = new Foo();

for (int i = 0; i < 3; i++) {
  tmp.setValue(i);
  list.add(tmp);
}

Здесь объект tmp был создан вне цикла. В результате один экземпляр объекта добавляется в список три раза. Экземпляр будет содержать значение 2, потому что это значение было передано во время последнего вызова setValue().

Чтобы исправить это, просто переместите конструкцию объекта внутри цикла:

List<Foo> list = new ArrayList<Foo>();        

for (int i = 0; i < 3; i++) {
  Foo tmp = new Foo(); // <-- fresh instance!
  tmp.setValue(i);
  list.add(tmp);
}
110
ответ дан 6 revs, 5 users 93% 4 September 2018 в 09:55
поделиться

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

List<Object> objects = new ArrayList<>(); 

for (int i = 0; i < length_you_want; i++) {
    SomeStaticClass myStaticObject = new SomeStaticClass();
    myStaticObject.tag = i;
    // Do stuff with myStaticObject
    objects.add(myStaticClass);
}

Вместо:

List<Object> objects = new ArrayList<>(); 

SomeStaticClass myStaticObject = new SomeStaticClass();
for (int i = 0; i < length; i++) {
    myStaticObject.tag = i;
    // Do stuff with myStaticObject
    objects.add(myStaticClass);
    // This will duplicate the last item "length" times
}

Здесь tag является переменной в SomeStaticClass проверить правильность приведенного выше фрагмента; у вас может быть другая реализация, основанная на вашем случае использования.

3
ответ дан 4castle 4 September 2018 в 09:55
поделиться

Каждый раз, когда вы добавляете объект в ArrayList, убедитесь, что вы добавили новый объект, а не уже использованный объект. Случается, что при добавлении одной и той же копии объекта этот объект добавляется в разные позиции в ArrayList. И когда вы вносите изменения в один, поскольку одна и та же копия добавляется снова и снова, все копии становятся затронутыми. Например, предположим, что у вас есть ArrayList:

ArrayList<Card> list = new ArrayList<Card>();
Card c = new Card();

Теперь, если вы добавите эту карту c в список, она не будет добавлена ​​никаких проблем. Он будет сохранен в месте 0. Но когда вы сохраните ту же Карту c в списке, она будет сохранена в местоположении 1. Так что помните, что вы добавили один и тот же 1 объект в два разных местоположения в списке. Теперь, если вы внесете изменения в объект Card c, объекты в списке в местах 0 и 1 также отражают это изменение, потому что они являются одним и тем же объектом.

Одним из решений было бы сделать конструктор класса Card, который принимает другой объект карты. Затем в этом конструкторе вы можете установить такие свойства следующим образом:

public Card(Card c){
this.property1 = c.getProperty1();
this.property2 = c.getProperty2(); 
... //add all the properties that you have in this class Card this way
}

И скажем, что у вас есть одна и та же 1 копия Карты, поэтому во время добавления нового объекта вы можете сделать это:

list.add(new Card(nameOfTheCardObjectThatYouWantADifferentCopyOf));
2
ответ дан Faraz Durrani 4 September 2018 в 09:55
поделиться

Имели ту же самую проблему с экземпляром календаря.

Неверный код:

Calendar myCalendar = Calendar.getInstance();

for (int days = 0; days < daysPerWeek; days++) {
    myCalendar.add(Calendar.DAY_OF_YEAR, 1);

    // In the next line lies the error
    Calendar newCal = myCalendar;
    calendarList.add(newCal);
}

Вам нужно создать НОВЫЙ объект календаря, который можно выполнить с помощью calendar.clone();

Calendar myCalendar = Calendar.getInstance();

for (int days = 0; days < daysPerWeek; days++) {
    myCalendar.add(Calendar.DAY_OF_YEAR, 1);

    // RIGHT WAY
    Calendar newCal = (Calendar) myCalendar.clone();
    calendarList.add(newCal);

}
2
ответ дан Ivan 4 September 2018 в 09:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: