我正在检查是否可以使用canForm
方法在此boggle板上形成指定的单词。该板具有graph
字段,表示相邻的图块。如果可以形成单词,我会执行DFS并将answer
设置为true
。
我理解为什么下面的代码不起作用:answer
是一个原语,它的值在每次递归时被复制,而初始answer
(在公共方法中)保持为false。
例如,如果我将boolean answer
更改为Set<String> answer = new HashSet<>()
,则在递归时将引用传递给集合,最后添加成功形成的单词并最终测试空白,它可以正常工作。
但是,如果我只是声明Boolean answer = new Boolean(false)
并传递此容器,为什么它不起作用?它可以直接传递对象的引用,但它会在赋值answer = true
时神秘地更改引用(通过调试器看到),并且不会重置初始answer
。我不明白。
public boolean canForm(String word) {
boolean answer = false;
int n = M * N;
char initial = word.charAt(0);
// for each tile that is the first letter of word
for (int u = 0; u < n; u++) {
char c = getLetter(u / N, u % N);
if (c == initial) {
boolean[] marked = new boolean[n];
marked[u] = true;
canForm(u, word, 1, marked, answer);
}
}
return !answer;
}
private void canForm(int u, String word, int d, boolean[] marked, boolean answer) {
if (word.length() == d) {
answer = true;
return;
}
for (int v : graph.adj(u)) {
char c = getLetter(v / N, v % N);
if (c == word.charAt(d) && !marked[v]) {
marked[v] = true;
canForm(v, word, d + 1, marked, answer);
}
}
}
答案 0 :(得分:4)
啊,你正在使用Java。这非常重要。
Java完全是一种价值传递语言。因此,当你调用canForm(int,String,int,boolean [],boolean)时,你做了两件事:
更改您创建的新变量的值不会对呼叫站点上这些变量的值产生任何影响。当方法调用结束时,您所做的任何重新分配都将丢失,并且不会对呼叫站点的值产生任何影响。
但是,对于数组或对象,传递的“值”实际上是对对象的引用。这可能有点令人困惑,但它就像调用者和方法每个人都拥有自己的共享邮箱个人密钥。要么丢失密钥,要么将密钥替换为不同的邮箱,而不影响对方访问邮箱的能力。
因此,该方法可以在不改变调用者引用的情况下更改引用(marked = new boolean[]
)的值。但是,如果方法在引用的结构(marked[0] = false
)内更改内容,则调用者将看到该内容。这就像打开共享邮箱的方法并更改了里面的邮件一样。无论您使用哪个键打开它,您都会看到相同的更改状态。
一个很好的分析:http://javadude.com/articles/passbyvalue.htm
一般来说: