【问题标题】:Passing ArrayList as a parameter将 ArrayList 作为参数传递
【发布时间】:2012-11-10 08:18:47
【问题描述】:

首先让我说我不能在这里放任何代码,因为我的笔记本电脑上的互联网无法正常工作,所以我通过手机发布了这个。好的,问题是说我有两个班:一班和二班。第一类有一个ArrayList 作为其属性之一,它从第二类调用一个void 方法并将ArrayList 作为参数传递。现在该方法初始化另一个ArrayList 并使其等于我传递的参数并对新的ArrayList 进行更改。有趣的是,即使是我原来作为参数传递的 ArrayList 也在发生变化。可能的原因是什么?

【问题讨论】:

  • 我猜是因为你在堆中有 2 个对同一个对象的引用。因此,对第一个引用的任何修改都会反映到另一个引用。有关详细信息,请参阅stackoverflow.com/a/9404727/597657
  • 列表是否发生了变化(删除/添加/重新排序的元素),还是列表中的元素(它们的属性)?

标签: java arrays arraylist


【解决方案1】:

问题在于,当您使用 = 使新的 ArrayList 成为原始的副本时,您只是创建了对同一 ArrayList 的新引用。把它想象成两个指向同一个对象的变量。

看看这个,它可能会帮助你了解发生了什么:Is Java "pass-by-reference" or "pass-by-value"?

为了解决您的问题,您需要使用“new”关键字创建一个新的 ArrayList,然后添加所有对象,或者使用 clone() 方法。

【讨论】:

    【解决方案2】:

    原因是当你传递一个 ArrayList 作为参数时,被调用的方法可以改变数组的内容。 ArrayList 包含对对象的引用。 如果你想避免某些类会改变你拥有的 ArrayList 的内容 返还 ArrayList 的副本,其中所有对象都是列表中对象的 clone()。

    使用 object.clone()

    ArrayList clonedCopy = new ArrayList(list1.size());
    for (Object obj : list1) {
      clonedCopy.add(obj.clone());
    }
    

    现在把这个 clonedCopy 还回去。但要确保 obj 是可克隆的!

    【讨论】:

    • 正确点,但更简单的代码是ArrayList copy = new ArrayList(incomingList);
    • @user949300 不!您的代码不会复制列表中的对象,它只会复制对它的引用。如果您的列表中有一个 Date 对象,并将您的复制列表提供给另一个类。其他类可以更改您列表中的 Date 对象!因此克隆,或尽可能使用原始类型(日期:更好)
    • 是的,关于使用原语/不可变的很好的一点。但是,这取决于您是否要允许其他类进行更改。由于 OP 提到方法调用是无效的,因此他希望允许更改似乎是合理的。否则,尚不清楚其他方法实际上会如何做任何事情。
    【解决方案3】:

    示例代码:

    public class MethodArguments {
    
    public static void main(String args[]) {
    
        ArrayList<String> a = new ArrayList<String>();
    
        a.add("Steve");
    
        a.add("Daniel");
        a.add("John");
        a.add("Maxi");
        a.add("Jeni");
    
        System.out.println(a);
    
        display(a);
    
        getSize(a);
    
    }
    
    static void display(ArrayList<String> arrayList1) {
    
        arrayList1.add("Pollard");
    
        System.out.println(arrayList1); // passing the arraylist values and
                                        // adding the element
    
    }
    
    static void getSize(ArrayList<String> arrayList1) {
    
        System.out.println(arrayList1.size()); // getting the size of arraylist
                                                // by passing arguments to
                                                // method
     }
    
    }
    

    输出:

    [史蒂夫、丹尼尔、约翰、马克西、珍妮]

    [史蒂夫、丹尼尔、约翰、马克西、珍妮、波拉德]

    6

    【讨论】:

      【解决方案4】:

      因为它们指向同一个引用。

      【讨论】:

        【解决方案5】:

        这是因为当你使新数组列表等于时,它指向同一个旧数组。

        这个小例子应该能说明问题。

        import java.util.ArrayList;
        import java.util.List;
        
        
        public class JavaApplication1 {
        
        
            public static void main(String[] args) {
        
                List <String> origList = new ArrayList<>();
                origList.add("a");
                origList.add("b");
        
                JavaApplication1 app = new JavaApplication1();
                app.addToList(origList);
        
                for(String str:origList){            
                    System.out.println(str);
                }
        
            }
        
            private void addToList(List<String> strList){
                System.out.println("inside addToList");
                List <String> newList = new ArrayList<>();
                // newList = strList; //This is how you are doing it
                newList.addAll(strList); //This is how you should do it.
        
                newList.add("x");
            }
        }
        

        【讨论】:

        • 我猜你在这里缺少类型注释new ArrayList&lt;&gt;();
        【解决方案6】:

        Java 中的= 运算符只会复制ArrayList 引用(对所有对象也是如此)。请参阅 this answer 以获取 ArrayList 的深层副本。

        【讨论】:

          猜你喜欢
          • 2014-05-04
          • 1970-01-01
          • 1970-01-01
          • 2021-07-22
          • 1970-01-01
          • 2015-11-08
          • 1970-01-01
          • 2012-04-22
          • 1970-01-01
          相关资源
          最近更新 更多