【问题标题】:Java Array List and object passingJava 数组列表和对象传递
【发布时间】:2013-03-15 19:39:33
【问题描述】:

我的代码中有一个字符串列表。我将该字符串列表传递给一个函数并对其进行修改。(我正在从列表中添加/删除几个元素)。但我不希望这些更改反映在调用者函数中。更改应仅反映在被调用函数中。但是由于对象是通过引用传递的,我认为这些变化都反映在这两个函数中。我怎样才能避免这种情况。请帮忙

【问题讨论】:

  • ArrayList newArrayList = (ArrayList) oldArrayList.clone();
  • 添加了额外的位:如果列表中的对象不是不可变的,请注意列表中的对象也可以在被调用函数中更改。列表克隆将创建浅拷贝而不是深拷贝。因此,如果您想保护列表中的对象 1) 进行深度克隆 2) 使对象不可变。

标签: java function object arraylist


【解决方案1】:

在方法内部,您可以显式地制作列表的副本:

private void method(ArrayList<String> list) {
    ArrayList<String> copy = new ArrayList<String>(list);
    // Rest of the method
}

【讨论】:

  • 有效吗?我认为它仍然会在列表中给出相同的对象引用。
  • @takrbuiam 如有疑问,请查看文档:ArrayList API。对于任何 Java 开发人员来说都是一个非常重要的工具。
  • @madth3 是的,我知道。我已经尝试过这种方法。我确信它不会复制对象。它会给出相同的对象引用。
  • 它将创建一个带有 same 对象的 new 列表。正如我在您的回答中评论的那样,当对象是不可变的时,它并不重要。
【解决方案2】:

你可以使用Clone方法。

caller(ArrayList<String> a)
{
    callee((List<String>)a.clone());
}

callee(List<String> aCloned)
{

}

【讨论】:

  • 据我所知,List 没有clone() 方法,因为它没有实现Cloneable。它的ArrayList 就是这样做的。
  • @R.J List 是一个接口,因此它没有任何方法。 .clone() 方法在Object 中定义,并且与直觉相反,与Cloneable 接口无关。检查the docs
  • @madth3 - 感谢您纠正我。但是我的编辑仍然正确,因为您仍然不能在 List&lt;String&gt; a 上调用 clone() 方法,但可以在 ArrayList&lt;String&gt; a 上调用。
  • 你说得对 ListObject 不相关且无法调用 .clone()
  • @R.J, madth3:感谢您消除混淆和更正。
【解决方案3】:

在将对象传递给函数之前,您必须对其进行复制。

【讨论】:

    【解决方案4】:

    在sub方法中使用原数组列表的新ArrayList。

    【讨论】:

      【解决方案5】:

      通常不推荐使用clone 方法。看到这个clone(): ArrayList.clone() I thought does a shallow copy

      不过你可以试试这个方法

      public void doOperation(List<String> list){
          List<String> duplicateList = new ArrayList(list);
          // add, or delete stuff on duplicateList
      }
      

      在这里,您使用ArrayList 的构造函数为您提供传入列表的新副本。

      【讨论】:

      • 是的,给出了新的列表引用,但存在相同的对象引用。
      • 但是您对这个列表所做的任何更改都不会影响原始列表。由于String 对象是不可变的,我猜你应该没有问题。
      【解决方案6】:

      您必须使用循环手动从旧列表创建新列表,并且需要传递给该方法。 即

         List<String> list=new ArrayList<>();
          list.add("first");
          list.add("last");
          List<String>list2 =new ArrayList<String>();
          for(String value:list)
          {
          list2.add(new String(value));
          }
          System.out.println("list2-->"+list2);
      

      因为new ArrayList&lt;String&gt;(list); 给出了新的列表引用,但对象仍然有相同的引用。

      编辑:

      public class ArrayCopy {
      
      
          public static void main(String[] args) {
      
              ArrayCopy arrayCopy=new ArrayCopy();
              arrayCopy.copyData();
      
          }
          public void copyData()
          {
              List<Test> oldList=new ArrayList<Test>();
              oldList.add(new Test("1",10));
              oldList.add(new Test("2",45));
              List<Test> newList =new ArrayList<Test>(oldList);
              System.out.println("newList-->"+newList);
      
              /**
               * New Copy of Data
               */
              List<Test> newList1 =new ArrayList<Test>();
              for(Test test:newList)
              {
                  newList1.add(copyProperty(test));
              }
              System.out.println("newList-->"+newList1);
          }
          private Test copyProperty(Test test)
          {
              Test newTest=new Test(test.getId(), test.getNumber());
              return newTest;
          }
          class Test{
              String id;
              int number;
              public Test(String id,int number) {
                  this.id=id;
                  this.number=number;
              }
              public String getId() {
                  return id;
              }
              public void setId(String id) {
                  this.id = id;
              }
              public int getNumber() {
                  return number;
              }
              public void setNumber(int number) {
                  this.number = number;
              }
          }
      }
      

      【讨论】:

      • 如果list 中的对象可以更改,那么您是对的,但是由于Strings 是不可变的,因此创建副本是没有用的。给定使用 ArrayList 构造函数的解决方案很好。 Cloneable.clone() 方法无关。
      • @madth3 查看我的可编辑答案。它有测试对象。可以吗?它仍然给出相同的对象引用。在调试模式下查看。
      • 我一直同意两个列表中的元素是相同的。我建议阅读 immutable objects 以了解为什么在某些情况下它并不重要。
      猜你喜欢
      • 1970-01-01
      • 2018-08-19
      • 2023-03-30
      • 1970-01-01
      • 2013-12-19
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      相关资源
      最近更新 更多