Vấn đề này có hai nguyên nhân điển hình:
Trường tĩnh
Nếu các đối tượng trong danh sách của bạn lưu trữ dữ liệu trong các trường tĩnh, thì mỗi đối tượng trong danh sách của bạn sẽ có vẻ giống nhau vì chúng có cùng giá trị. Hãy xem xét lớp học dưới đây:
public class Foo {
private static int value;
public Foo(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Trong ví dụ đó, chỉ có một int value
cái được chia sẻ giữa tất cả các trường hợp Foo
bởi vì nó được khai báo static
. (Xem hướng dẫn "Hiểu về các thành viên trong lớp" .)
Nếu bạn thêm nhiều Foo
đối tượng vào danh sách bằng cách sử dụng mã bên dưới, mỗi đối tượng sẽ trả về 3
từ một lệnh gọi đến getValue()
:
for (int i = 0; i < 4; i++) {
list.add(new Foo(i));
}
Giải pháp rất đơn giản - không sử dụng các static
từ khóa cho các trường trong lớp của bạn trừ khi bạn thực sự muốn các giá trị được chia sẻ giữa mọi trường hợp của lớp đó.
Thêm cùng một đối tượng
Nếu bạn thêm một biến tạm thời vào danh sách, bạn phải tạo một phiên bản mới của đối tượng bạn đang thêm, mỗi lần lặp lại. Hãy xem xét đoạn mã sai sau:
List<Foo> list = new ArrayList<Foo>();
Foo tmp = new Foo();
for (int i = 0; i < 3; i++) {
tmp.setValue(i);
list.add(tmp);
}
Ở đây, tmp
đối tượng được xây dựng bên ngoài vòng lặp. Kết quả là, cùng một đối tượng được thêm vào danh sách ba lần. Cá thể sẽ giữ giá trị 2
, vì đó là giá trị được truyền trong lần gọi cuối cùng setValue()
.
Để khắc phục điều này, chỉ cần di chuyển cấu trúc đối tượng bên trong vòng lặp:
List<Foo> list = new ArrayList<Foo>();
for (int i = 0; i < 3; i++) {
Foo tmp = new Foo();
tmp.setValue(i);
list.add(tmp);
}