如果将Java ArrayList作为参数传递给函数返回void并在函数中修改,它是如何被修改的?可能会在传值上混淆

问题描述 投票:1回答:2

我有一个Java代码块,它通过将ArrayList传递给方法,修改方法中的列表并返回void来修改ArrayList。我认为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)时不会修改weaved数组,但是在调用weaveLists()之后修改了weaved数组,即使它返回void。

java recursion arraylist pass-by-value
2个回答
0
投票

您创建一个weaved引用存储在内存中的ArrayList对象。当你调用new操作符然后在内存中分配一个新对象。然后你将参考weaved传递给weaveLists()方法。这个方法有一个引用result,但这只是一个引用内存中相同对象的引用,因为只有new操作符分配一个新内存。因此,weaveLists()方法修改您的原始ArrayList。这是你应该理解的一个主要特征,我建议你阅读传值和传递参考之间的区别。


0
投票

简而言之 - 你误解了Java中的pass-by-value意味着什么。

如果你传递一个对象(在这种情况下是列表)并操纵它的元素而不改变它的引用,它就是你传递的同一个对象,对象(列表)本身没有任何改变,它具有传递给函数时的相同引用,但更改确实适用于任何被操纵的元素。

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

查看this问题的最佳答案,或者阅读一些与pass-by-value相关的java基础知识。使用this博客或您可能更喜欢的任何其他博客。

© www.soinside.com 2019 - 2024. All rights reserved.