Ця проблема має дві типові причини:
Статичні поля, що використовуються об'єктами, які ви зберігаєте у списку
Випадково додавши той самий об’єкт до списку
Статичні поля
Якщо об’єкти у вашому списку зберігають дані у статичних полях, кожен об’єкт у вашому списку виявиться однаковим, оскільки вони містять однакові значення. Розглянемо клас нижче:
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);
}