我想知道这两个代码之间的区别,即使它们产生相同的输出:
代码1:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return x;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
代码2:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return 0;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
它们都输出15但是第二个代码也输出15而不是零?我的理解是最后一次调用将是代码2的add(0)并且它将返回零。我也想知道它是否可以使用多个return语句或使用单个return语句并用局部变量替换其余的语句。我记得读单输入单一退出模型是一种很好的做法。
答案 0 :(得分:4)
这是一种递归方法,因此在x != 0
时,您将返回“x
添加到使用(x-1)
再次调用方法”的结果。最终通话将始终返回x == 0
或constant = 0
,因此您将从两个版本返回15
。
单次回报与多次回归是一个有争议的问题。前者应该优先作为规则。通常,很明显可以接受多个return语句,因为使用它们比使用设计单个出口点所需的替代代码构造更容易理解它们。另请注意,您可以将add
重写为:
public static int add(int x) {
return x == 0 ? 0 : (x + add(x-1));
}
版本1:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (x = 0)
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
第2版:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (constant = 0) // the only difference
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
答案 1 :(得分:0)
使用多个return
语句与使用单个退出点无法通过简单的单行答案来回答。我想你能得到的最好答案是“这取决于你公司的标准”。
单点退出是一个非常好的标准,即使我个人不赞同它。你最终得到的方法总是只有一个return
语句,所以在编辑其他人的代码时,你永远不会找到那些可能的return
语句。我相信以前用C编码的开发人员倾向于遵循这个标准(见question)。
我可以使用多个return
语句来帮助简化代码。我喜欢使用它的一个案例是防止我的代码中的级联括号。例如,在以下示例中:
private int doSomething (int param) {
int returnCode;
if (param >= 0) {
int someValue = param * CONSTANT_VALUE;
if (isWithinExpectedRange (someValue)) {
if (updateSomething (someValue)) {
returnCode = 0;
} else {
returnCode = -3;
}
} else {
returnCode = -2;
}
} else {
returnCode = -1;
}
return returnCode;
}
我发现这种类型的编码在阅读时非常混乱。我倾向于将此类代码更改为:
private int doSomething (int param) {
if (param < 0) {
return -1;
}
int someValue = param * CONSTANT_VALUE;
if (!isWithinExpectedRange (someValue)) {
return -2;
}
if (!updateSomething (someValue)) {
return -3;
}
return 0;
}
第二个例子看起来更干净,更清晰。当实际代码在else
块中有一些额外的编码时更是如此。
同样,这是个人品味。有些公司可能会强制执行一个退出点,有些可能不会,有些开发人员更喜欢单一退出点。最重要的是,如果您的环境中有可供您遵循的指南,那么请执行此操作。如果没有,那么你可以部分根据这些论点选择你自己的偏好基础。