java - 不知何故,在递归过程中,对象在 list.add(object) 之后发生了变异。解释?

标签 java recursion maze

所以我目前正在处理的任务相当简单。我必须找到每个给定迷宫内给定起点的所有导出,并将路径打印到屏幕上。可以有多个导出。迷宫可以如下所示:

    #####.###
    #.....#.#
    #.#####.#
    #.#.....#
    #.#.###.#
    #.#.#.#.#
    #.....#.#
    #########

正方形就是正方形。点是 WhiteSquare,主题标签是 BlackSquare,它们都是 Square 的子类。 Opening 是 WhiteSquare 的子类。

这个想法是在我当前所在的方 block 的每个邻居上调用 go() 。黑色方 block 中的方法 go() 不执行任何操作,因此只有白色方 block 在这方面起作用。每次调用 go() 时,都会将包含所有先前访问过的方 block 的列表副本作为参数发送,这样它就不会在前一个邻居上调用 go()。这是因为我希望该算法也适用于循环迷宫。一旦我遇到一个空位,我就会将该路径添加到起始方 block 的可能导出列表(列表列表)中。这是代码:

public void go(ArrayList<Rute> path, WhiteSquare startSquare) {
    ArrayList<Rute> pathCopy = path;
    pathCopy.add(this);
    if (this instanceof Opening) {
        startSquare.addPossibleExit(pathCopy);
        return;
    }
    for (Square neighbour : this.getNeighbours()) {
        if (!path.contains(neighbour)) {
            neighbour.go(pathCopy, startSquare);
        }
    }
}

System.out.println(startSquare.exits) 找到空位后将打印正确的路径。一切都很好。然而,如果在找到空位后有更多的方 block 要经过,那么导出中的正确路径将以某种方式开始在列表本身内增长,即使在添加了它之后也是如此。我不明白。上面迷宫中 startRoute 为 (3, 1) 的示例(伪代码):

System.out.println(Square.toString() + " go. " + Exits: " + startSquare.getExits())

if (this instanceof Opening) {print("Opening found!")}

将打印出:

(3, 1) go. Exits: []
(2, 1) go. Exits: []
(1, 1) go. Exits: []
(1, 2) go. Exits: []
(1, 3) go. Exits: []
(1, 4) go. Exits: []
(1, 5) go. Exits: []
(0, 5) go. Exits: []
Opening found!
(4, 1) go. Exits: [[(3, 1), (2, 1), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (0, 5)]]
(5, 1) go. Exits: [[(3, 1), (2, 1), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (0, 5), (4, 1)]]
(6, 1) go. Exits: [[(3, 1), (2, 1), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (0, 5), (4, 1), (5, 1)]]

我无法解释这里发生了什么。我不希望路径在添加到导出后继续增长。

最佳答案

pathCopy 不是 new ArrayList,它是对 path 的引用,当您添加到 pathCopy 时,它实际上添加到 path

您可以创建一个新的ArrayList,然后使用.addAll(path)将所有值复制到新的ArrayList

Java 中的每个变量都是指针,除了基本类型(如 int、bool)。 当您分配“复杂”类型时,它分配的是指针而不是值。

关于引用和值(value)的解释可以参见here

关于java - 不知何故,在递归过程中,对象在 list.add(object) 之后发生了变异。解释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49819559/

相关文章:

java - 使用 Android AdapterView.OnItemClick 监听器重定向到新的空白 Activity

java - Java 指针写入是原子的吗?

java - 如何在 jaxb marshaller 中添加 DOCTYPE

java - 如何对来自不同项目的关联类进行排序

haskell - 代数数据类型的递归自下而上遍历

java - 模型之间的交互 ​​MVC Java

python - 递归枚举 JSON 层次结构父/子到字典

algorithm - 具有最大和加约束的最长递增子序列 - 可以跳过允许的元素数量

c++ - 使用 C++ 从 .txt 解决迷宫

c - C中的回溯迷宫求解器