gpt4 book ai didi

java - 为什么我的 ArrayList 包含添加到列表中的最后一项的 N 个副本?

转载 作者:IT老高 更新时间:2023-10-28 13:50:52 26 4
gpt4 key购买 nike

我正在向 ArrayList 添加三个不同的对象,但该列表包含我添加的最后一个对象的三个副本。

例如:

for (Foo f : list) {
System.out.println(f.getValue());
}

预期:

0
1
2

实际:

2
2
2

我犯了什么错误?

注意:这是针对本网站上出现的许多类似问题的规范问答。

最佳答案

这个问题有两个典型的原因:

  • 您存储在列表中的对象使用的静态字段

  • 不小心将相同的对象添加到列表中

静态字段

如果列表中的对象将数据存储在静态字段中,则列表中的每个对象看起来都是相同的,因为它们具有相同的值。考虑下面的类:

public class Foo {
private static int value;
// ^^^^^^------------ - Here's the problem!

public Foo(int value) {
this.value = value;
}

public int getValue() {
return value;
}
}

在该示例中,只有一个 int valueFoo 的所有实例之间共享,因为它被声明为 static。 (参见 "Understanding Class Members" 教程。)

如果您使用下面的代码将多个 Foo 对象添加到列表中,每个实例将从对 getValue() 的调用中返回 3 :

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);
}

关于java - 为什么我的 ArrayList 包含添加到列表中的最后一项的 N 个副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19843506/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com