此问题有两个典型原因:
-
存储在列表中的对象所使用的静态字段
-
意外将同一对象添加到列表中
静态字段
如果列表中的对象在静态字段中存储数据,则列表中的每个对象看起来都相同,因为它们包含相同的值。考虑以下类:
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
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);
}