当 Java ArrayList 作为参数传递给返回 void 并在函数中修改的函数时,如何修改?可能会对传递值感到困惑

How is a Java ArrayList modified when passed as parameter to function that returns void and modified in function? May be confused on pass-by-value

提问人:user2788960 提问时间:4/27/2019 更新时间:4/27/2019 访问量:1330

问:

我有一个 Java 代码块,它通过将 ArrayList 传递到方法中来修改 ArrayList,修改方法中的列表,然后返回 void。我以为 Java 的 pass-by-value 会导致原始 ArrayList 不被修改。我有什么误解?

public class Question {

    public static void weaveLists(LinkedList<Integer> first, LinkedList<Integer> second, ArrayList<LinkedList<Integer>> results, LinkedList<Integer> prefix) {
        /* One list is empty. Add the remainder to [a cloned] prefix and
         * store result. */
        if (first.size() == 0 || second.size() == 0) {
            LinkedList<Integer> result = (LinkedList<Integer>) prefix.clone();
            result.addAll(first);
            result.addAll(second);
            results.add(result);
            return;
        }

        /* Recurse with head of first added to the prefix. Removing the
         * head will damage first, so we’ll need to put it back where we
         * found it afterwards. */
        int headFirst = first.removeFirst();
        prefix.addLast(headFirst);
        weaveLists(first, second, results, prefix);
        prefix.removeLast();
        first.addFirst(headFirst);

        /* Do the same thing with second, damaging and then restoring
         * the list.*/
        int headSecond = second.removeFirst();
        prefix.addLast(headSecond);
        weaveLists(first, second, results, prefix);
        prefix.removeLast();    
        second.addFirst(headSecond);
    }

    public static ArrayList<LinkedList<Integer>> allSequences(TreeNode node) {
        ArrayList<LinkedList<Integer>> result = new ArrayList<LinkedList<Integer>>();

        if (node == null) {
            result.add(new LinkedList<Integer>());
            return result;
        } 

        LinkedList<Integer> prefix = new LinkedList<Integer>();
        prefix.add(node.data);

        /* Recurse on left and right subtrees. */
        ArrayList<LinkedList<Integer>> leftSeq = allSequences(node.left);
        ArrayList<LinkedList<Integer>> rightSeq = allSequences(node.right);

        /* Weave together each list from the left and right sides. */
        for (LinkedList<Integer> left : leftSeq) {
            for (LinkedList<Integer> right : rightSeq) {
//This is the part I don't understand
                ArrayList<LinkedList<Integer>> weaved = new ArrayList<LinkedList<Integer>>();
                weaveLists(left, right, weaved, prefix);
                result.addAll(weaved);
            }
        }
        return result;
    }

}

我希望在调用 result.addAll(weaved) 时不会修改编织数组,但在调用 weaveLists() 后会修改编织数组,即使它返回 void。

Java 递归 arraylist 按值传递

评论

0赞 Pshemo 4/27/2019
这应该会有所帮助:javaranch.com/campfire/StoryCups.jsp,javaranch.com/campfire/StoryPassBy.jsp
0赞 Pshemo 4/27/2019
“但是在调用 weaveLists() 后修改了编织数组,即使它返回 void” 返回类型与方法参数在方法中的使用方式无关,我不确定你为什么不这么认为。

答:

0赞 Sergey Chepurnov 4/27/2019 #1

创建对存储在内存中的对象的引用。当您调用 operator 时,会在内存中分配一个新对象。然后,将引用传递给该方法。 此方法有一个引用,但这只是一个引用内存中同一对象的引用,因为只有运算符分配新的内存。因此,该方法修改了原始的 ArrayList。这是您应该了解的主要功能,我建议您阅读按值传递按引用传递之间的区别。weavedArrayListnewweavedweaveLists()resultnewweaveLists()

0赞 kiselitza 4/27/2019 #2

简而言之,回答这个问题 - 您误解了 Java 中的传递值是什么意思

如果你传递一个对象(在本例中为 list)并在不更改其引用的情况下操作它的元素,则它是您传递的相同对象,对象(列表)本身没有任何变化,它具有传递给函数时相同的引用,但更改确实适用于任何作的元素。

在此上下文中,按值传递仅意味着,如果您在函数中创建了给定列表的新实例,然后对其进行了操作,则不会对原始列表进行任何更改,因为该变量将被视为局部变量,而不是传递的变量。

查看问题的最佳答案,或者只是阅读一些与传递值相关的 Java 基础知识。使用博客,或任何其他您可能更喜欢的博客。

评论

0赞 arcy 4/27/2019
实际上,我不认为你关于按值传递含义的例子很有帮助,因为如果代码复制并操作它,无论它如何传递,它都不会影响传入的项目。我认为的一种方式是,根据设计,被调用的方法不能创建一个新对象并将其作为传入的参数之一返回;被调用方法创建的对象可以返回给调用方的唯一方法是将其作为方法的返回值返回。