Java 传递对对象的引用
我正在检查是否可以使用Java 传递对对象的引用,java,Java,我正在检查是否可以使用canForm方法在此boggle板上形成指定的单词。电路板上有一个图形字段,指示相邻的磁贴。我做了一个DFS,并将answer设置为true,如果单词可以组成 我理解为什么下面的代码不起作用:answer是一个原语,它的值在每次递归时都被复制,并且初始的answer(在public方法中)保持为false 例如,如果我将boolean answer更改为Set answer=new HashSet(),则在递归中传递对集合的引用,最终添加成功形成的单词并测试其是否为空,它
canForm
方法在此boggle板上形成指定的单词。电路板上有一个图形
字段,指示相邻的磁贴。我做了一个DFS,并将answer
设置为true
,如果单词可以组成
我理解为什么下面的代码不起作用:answer
是一个原语,它的值在每次递归时都被复制,并且初始的answer
(在public方法中)保持为false
例如,如果我将boolean answer
更改为Set 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);
}
}
}
public boolean canForm(字符串字){
布尔答案=假;
int n=M*n;
字符首字母=word.charAt(0);
//对于单词的第一个字母的每个瓷砖
对于(int u=0;u
啊,你在用Java。这非常重要
Java完全是一种传递值语言。因此,当您调用canForm(int,String,int,boolean[],boolean)时,您正在做两件事:
- 您正在canForm方法的范围内创建5个新变量
- 您正在使用调用站点中的值初始化它们
marked=newboolean[]
),而不改变调用方的引用。但是,如果该方法更改了引用结构中的内容(标记为[0]=false
),则调用者将看到该方法。这就像该方法打开了共享邮箱并更改了里面的邮件一样。无论使用哪个键打开,都会看到相同的更改状态
伟大的分析:
一般而言:
- 如果要从方法返回值,则该值应为该方法的返回值。这使得代码更容易理解,不太可能有副作用,并且可能使编译器更容易优化
- 如果要返回两个值,请创建一个对象来保存这两个值(在许多语言和框架中都有一个称为“Tuple”的通用类型安全容器)
- 如果确实需要在函数调用之间移动状态(通常不需要),请使用对象将其包装起来,以获得与按引用传递语义等价的语义。这就是将结果添加到共享集时所做的基本操作。请注意:带有副作用的编程,无论是共享对象还是全局状态,都容易出现缺陷。当你传递一个可变的物体时,很难在你的头脑中保留所有潜在的变化机制。如果只能通过返回值来完成作业,则应尝试这样做。有些人可能会称之为“功能[编程]风格”
- 当您给两个具有不同意图的方法赋予相同的名称时,这会造成混淆,读者和某些情况下的编译器都会感到混淆。具体点。我们没有角色用完的危险
- 最后,您可能希望了解尾部递归。由于这个循环,我相信这个实现可能是一个等待发生的堆栈溢出——只要给它一个比堆栈深度更长的字符串
- 您正在canForm方法的范围内创建5个新变量
- 您正在使用调用站点中的值初始化它们
- 啊,你在用Java。这非常重要
Java完全是一种传递值语言。因此,当您调用canForm(int,String,int,boolean[],boolean)时,您正在做两件事:
marked=new boolean[]
)