不知何故,对象在递归期间在 list.add(object) 之后发生了变化.解释?



所以我目前正在处理的任务相当简单。我必须在每个给定迷宫中找到给定起点的所有出口,并将路径打印到屏幕上。可以有多个出口。迷宫可能看起来像这样:

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

正方形就是正方形。点是WhiteSquare,标签是BlackSquare,它们都是Square的子类。开口是WhiteSquare的一个子类。

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

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) 找到开口后将打印正确的路径。一切都很好。但是,如果在找到开口后有更多的方块要通过,则退出的正确路径将以某种方式开始在列表本身内增长,即使在添加之后也是如此。我不明白。示例,如果 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

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

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

有关参考和值的解释可以在这里找到

正如关于数组列表复制的问题中提到的,你并没有真正通过赋值复制数组。您应该创建一个新数组并复制项目。

ArrayList<Rute> pathCopy = new ArrayList<>(path);

最新更新