【问题标题】:Java list changed when update another one更新另一个时 Java 列表发生了变化
【发布时间】:2018-04-21 00:19:29
【问题描述】:

假设我们有:

public class Test {

    private List<String> mWorkList;
    private List<String> mOriginalList;

    public Test(List<String> list) {
        mWorkList = list;
        mOriginalList = list;
    }

    public void updateData(List<String> newList) {
        mWorkList.clear();
        mWorkList.addAll(newList);
    }
}

我只想更改mWorkList,但当我调用updateData(List&lt;String&gt;) 时,mOriginalList 也会更改。 那么我应该怎么做才能保持 mOriginalList 最初在构造函数中分配?

【问题讨论】:

  • 两者都指向List&lt;String&gt; list的同一个实例...你需要创建一个List的新实例,看看如何将here列表复制到一个新实例中

标签: java


【解决方案1】:

在 Java 中,您通过变量的引用传递变量。这意味着每当您执行像mWorkList = list 这样的赋值时,变量mWorkList 将指向内存中list 当前指向的相同 位置。如果你做mOriginalList = list,那么mOriginalList 也会指向那个位置。 IE。 所有三个列表在此时引用同一个对象


如果您想要独立列表,您需要将列表中的所有值复制新列表,如下所示:

List<String> myList = new ArrayList<>(otherList);

ArrayList 的这个构造函数自动添加其他列表中的所有值,这里是它的documentation


您的代码可能如下所示:

public Test(List<String> list) {
    mWorkList = new ArrayList<>(list);
    mOriginalList = new ArrayList<>(list);
}

或者,如果您不打算更改 mOriginalList,您也可以将其保留为 mOriginalList = list。但是请记住,如果用户对list(来自您班级的外部)进行更改,它们也会反映在您的mOriginalList 中,这很容易导致讨厌错误

【讨论】:

    【解决方案2】:

    您将两个列表设置为具有相同的实例引用

    mWorkList = list;
    mOriginalList = list;
    

    您需要通过复制列表为mOriginalList 创建一个新实例。这可以通过ArrayList(Collection) 的构造函数之一来完成。

    mOriginalList = new ArrayList<>(list);
    

    请注意,两个列表中的实例是相同的,所以如果您更新list 中的实例,它将在mOriginalList 中更改。如果您也想断开该链接,则需要克隆列表及其内容。

    【讨论】:

      【解决方案3】:

      您应该在函数Test 中创建新的List 对象,因为您的所有列表都引用一个变量

      public Test(List<String> list) {
          mWorkList = new ArrayList<>(list);
          mOriginalList = new ArrayList<>(list);
      }
      

      【讨论】:

      • 详细说明:对上述列表有不同的引用。然后你使用 mWorkList.addAll(list); mOriginalList.addAll() 填充列表中的数据
      • @YegorBabarykin OP 必须等待至少 15 分钟 才能接受。这样可以确保其他人也有机会发布好的答案 (Time limit on accepting an answer)。
      • @Zabuza 谢谢,我不知道这条规则
      【解决方案4】:

      每当您将一个对象分配给另一个对象时,只会分配引用(浅拷贝)。您应该调用复制构造函数来进行深层复制。

      public class Test {
      
          private List<String> mWorkList;
          private List<String> mOriginalList;
      
      
          public Test(List<String> list) {
              mWorkList = new ArrayList<>(list);
              mOriginalList = new ArrayList<>(list);
          }
      
          public void updateData(List<String> newList) {
              mWorkList.clear();
              mWorkList.addAll(newList);
          }
      }                  
      

      【讨论】:

        【解决方案5】:

        在java中,每个变量都是一个引用,所以在这种情况下,如果你改变其中一个变量,两个变量都会改变是正常的。

        要保留副本,您必须创建一个新对象并克隆原始对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-01-15
          • 2014-04-22
          • 2018-06-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多