将ArrayList作为参数传递

12

首先声明,由于我的笔记本电脑上的互联网无法使用,因此我通过手机发布这篇文章,无法提供任何代码。好了,问题是这样的:假设我有两个类:类一和类二。类一具有一个ArrayList作为其属性,并从类二调用了一个void方法,并将该ArrayList作为参数传递。现在,该方法初始化另一个ArrayList并使其等于由我传递的参数,并对该新的ArrayList进行更改。有趣的是,即使是作为参数传递的原始ArrayList也在发生变化。可能的原因是什么?


我猜是因为您在堆中有两个指向同一对象的引用。因此,对第一个引用的任何修改都会反映到另一个引用上。有关更多详细信息,请参见https://dev59.com/d2ox5IYBdhLWcg3wIRD3#9404727。 - Eng.Fouad
列表是否发生了变化(元素被删除/添加/重新排序),还是列表中的元素(它们的属性)发生了变化? - Andy
6个回答

6
问题在于当你使用等号将新的ArrayList复制到原始列表时,你只是创建了一个指向相同ArrayList的新引用。可以把它想象成两个变量指向同一个对象。
看一下这个链接,它可能会帮助你理解发生了什么:Java是按引用传递还是按值传递? 为了解决你的问题,你需要使用“new”关键字创建一个新的ArrayList,然后添加所有的对象,或者使用clone()方法。

3
理由是,当你把一个ArrayList作为参数传递时,被调用的方法可以改变数组的内容。ArrayList包含对对象的引用。 如果您想避免某个类更改您的ArrayList的内容,则必须返回副本,其中所有内部对象都是列表中对象的clone()s。
使用object.clone()。
ArrayList clonedCopy = new ArrayList(list1.size());
for (Object obj : list1) {
  clonedCopy.add(obj.clone());
}

现在把这个克隆副本返回。但是确保 obj 是可克隆的!

这是一个正确的点,但更简单的代码可以是 ArrayList copy = new ArrayList(incomingList); - user949300
3
不!你的代码不会复制列表中的对象,它只会复制一个指向对象的引用。如果您的列表中有日期对象,并将复制后的列表交给另一个类,那么该类可以更改列表内的日期对象!因此,如果可能的话,请使用克隆或基本数据类型(日期:最好使用长整型)。 - AlexWien
真的,使用原始类型/不可变对象是个好点子。但这取决于你是否想让其他类进行更改。由于OP提到方法调用为空,似乎他想允许更改。否则,不清楚其他方法如何实际执行任何操作。 - user949300

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


1
因为它们指向相同的引用。

0

这是因为当你将其等于时,新的数组列表指向同一旧数组。

这个小例子应该可以澄清它。

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<>(); - user5047085

0
在Java中,= 运算符只会复制 ArrayList 引用(所有对象都是如此)。请参见 this answer 以制作 ArrayList 的深拷贝。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接