gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 17:27:28 25 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 值Foo 的所有实例之间共享,因为它被声明为 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/61190111/

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