У этой проблемы есть две типичные причины:
Статические поля, используемые объектами, которые вы сохранили в списке
Случайное добавление того же объекта в список
Статические поля
Если объекты в вашем списке хранят данные в статических полях, каждый объект в вашем списке будет выглядеть одинаково, потому что они содержат одинаковые значения. Рассмотрим класс ниже:
public class Foo {
private static int value;
public Foo(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
В этом примере есть только один, int value
который используется всеми экземплярами, Foo
потому что он объявлен static
. (См. Учебник «Общие сведения о членах класса» .)
Если вы добавите несколько Foo
объектов в список, используя приведенный ниже код, каждый экземпляр вернется 3
после вызова к 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();
tmp.setValue(i);
list.add(tmp);
}
tmp
) добавляется в список трижды. И этот объект имеет значение два из-за вызоваtmp.setValue(2)
на последней итерации цикла.you must create a new instance each time you loop
в разделеAdding the same object
: обратите внимание, что упомянутый экземпляр относится к объекту, который вы добавляете, а НЕ к объекту, к которому вы его добавляете.Ваша проблема связана с типом,
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
чтобы проверить правильность приведенного выше фрагмента; у вас может быть другая реализация в зависимости от вашего варианта использования.источник
static
»? Что для вас будет нестатическим классом?public class SomeClass{/*some code*/}
& статический:public static class SomeStaticClass{/*some code*/}
. Надеюсь, теперь стало понятнее.Была такая же проблема с экземпляром календаря.
Неверный код:
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); }
источник
Каждый раз, когда вы добавляете объект в ArrayList, убедитесь, что вы добавляете новый объект, а не уже используемый объект. Происходит то, что когда вы добавляете одну и ту же копию объекта, этот же объект добавляется в разные позиции в ArrayList. И когда вы вносите изменения в один, поскольку одна и та же копия добавляется снова и снова, это затрагивает все копии. Например, скажем, у вас есть такой список ArrayList:
ArrayList<Card> list = new ArrayList<Card>(); Card c = new Card();
Теперь, если вы добавите эту Карту c в список, она добавится без проблем. Он будет сохранен в ячейке 0. Но когда вы сохраните ту же Карту c в списке, она будет сохранена в ячейке 1. Так что помните, что вы добавили один и тот же объект 1 в два разных местоположения в списке. Теперь, если вы измените этот объект Card c, объекты в списке в местоположениях 0 и 1 также отразят это изменение, потому что это один и тот же объект.
Одним из решений было бы создать конструктор в классе Card, который принимает другой объект 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 }
Допустим, у вас есть одна и та же копия Card, поэтому во время добавления нового объекта вы можете сделать это:
list.add(new Card(nameOfTheCardObjectThatYouWantADifferentCopyOf));
источник
Это также может быть следствием использования той же ссылки вместо использования новой.
List<Foo> list = new ArrayList<Foo>(); setdata(); ...... public void setdata(int i) { Foo temp = new Foo(); tmp.setValue(i); list.add(tmp); }
Вместо:
List<Foo> list = new ArrayList<Foo>(); Foo temp = new Foo(); setdata(); ...... public void setdata(int i) { tmp.setValue(i); list.add(tmp); }
источник