为什么我的 ArrayList 包含添加到列表中的最后一项的 N 个副本? [英] Why does my ArrayList contain N copies of the last item added to the list?

查看:15
本文介绍了为什么我的 ArrayList 包含添加到列表中的最后一项的 N 个副本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将三个不同的对象添加到 ArrayList,但该列表包含我添加的最后一个对象的三个副本.

例如:

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

预期:

<预><代码>012

实际:

222

我犯了什么错误?

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

解决方案

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

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

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

静态字段

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

公共类 Foo {私有静态整数值;//^^^^^^------------ - 问题来了!公共 Foo(int 值) {this.value = 值;}公共 int getValue() {返回值;}}

在那个例子中,只有一个 int valueFoo 的所有实例之间共享,因为它被声明为 static.(请参阅了解类成员" 教程.)

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

for (int i = 0; i <4; i++) {list.add(new Foo(i));}

解决方案很简单 - 不要对类中的字段使用 static 关键字,除非您确实希望在该类的每个实例之间共享值.

添加相同的对象

如果向列表中添加临时变量,则每次循环时都必须为要添加的对象创建一个新实例.考虑以下错误的代码片段:

Listlist = new ArrayList();Foo tmp = new Foo();for (int i = 0; i <3; i++) {tmp.setValue(i);list.add(tmp);}

这里,tmp 对象是在循环外构造的.结果,相同的对象实例被添加到列表中三次.该实例将保存值 2,因为这是在最后一次调用 setValue() 期间传递的值.

要解决这个问题,只需在循环内移动对象结构:

Listlist = new ArrayList();for (int i = 0; i <3; i++) {Foo tmp = new Foo();//<-- 新鲜的实例!tmp.setValue(i);list.add(tmp);}

I'm adding three different objects to an ArrayList, but the list contains three copies of the last object I added.

For example:

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

Expected:

0
1
2

Actual:

2
2
2

What mistake have I made?

Note: this is designed to be a canonical Q&A for the numerous similar issues that arise on this site.

解决方案

This problem has two typical causes:

  • Static fields used by the objects you stored in the list

  • Accidentally adding the same object to the list

Static Fields

If the objects in your list store data in static fields, each object in your list will appear to be the same because they hold the same values. Consider the class below:

public class Foo {
  private static int value; 
  //      ^^^^^^------------ - Here's the problem!
  
  public Foo(int value) {
    this.value = value;
  }
  
  public int getValue() {
    return value;
  }
}

In that example, there is only one int value which is shared between all instances of Foo because it is declared static. (See "Understanding Class Members" tutorial.)

If you add multiple Foo objects to a list using the code below, each instance will return 3 from a call to getValue():

for (int i = 0; i < 4; i++) {      
  list.add(new Foo(i));
}

The solution is simple - don't use the static keywords for fields in your class unless you actually want the values shared between every instance of that class.

Adding the Same Object

If you add a temporary variable to a list, you must create a new instance of the object you are adding, each time you loop. Consider the following erroneous code snippet:

List<Foo> list = new ArrayList<Foo>();    
Foo tmp = new Foo();

for (int i = 0; i < 3; i++) {
  tmp.setValue(i);
  list.add(tmp);
}

Here, the tmp object was constructed outside the loop. As a result, the same object instance is being added to the list three times. The instance will hold the value 2, because that was the value passed during the last call to setValue().

To fix this, just move the object construction inside the loop:

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

这篇关于为什么我的 ArrayList 包含添加到列表中的最后一项的 N 个副本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆