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