我尝试非常简单的测试:
public static void main(String[] args) {
test(2);
}
public static void test(int i) {
i--;
System.out.println("i="+i);
if (i < 0)
return;
System.out.println("test1");
test(i);
System.out.println("test2");
test(i);
}
输出:
i=1
test1
i=0
test1
i=-1
test2
i=-1
test2
i=0
test1
i=-1
test2
i=-1
我无法理解为什么第二次调用(test2)中的变量i在已经为0之后的值为0? 感谢。
答案 0 :(得分:5)
我发现缩进输出将有助于解释这些事情,这里的每个级别对应于调用堆栈的深度(你有多少递归),序列对应于执行这些操作的时间:
i=1
test1
i=0 (invoked on the test1 path)
test1
i=-1 (invoked on the test1 path)
test2
i=-1 (invoked on the test2 path)
test2
i=0 (invoked on the test2 path)
test1
i=-1 (invoked on the test 1 path)
test2
i=-1 (invoked on the test 2 path)
请注意,在每个缩进级别下,标题“test1”和“test2”下都有调用,这是因为您在每个标题下递归调用test
,因此每个> 执行test
你两次递送。
让我们稍微备份并采取更简单的案例,如果您要执行test(1)
,您可能会看到:
i=0
test1
i=-1
test2
i=-1
因为您在标题“test1”和“test2”下调用test
,导致两个路径被导航,一个路径位于“test1”标题下,另一个路径位于“test2”标题下。
当您致电test(2)
时,您的代码大致会这样做:(省略递归)
(i = 2)
Decrement i (i = 1)
Print i
Print "test1"
Call test(i) (test(1))
Print "test2"
Call test(i) (test(1))
...并记住,每次调用test(1)
时,您的代码大致会这样做:(省略递归)
(i = 1)
Decrement i (i = 0)
Print i
Print "test 1"
Call test(i) (test(0))
Print "test 2"
Call test(i) (test(0))
如果您使用test(1)
块的输出替换第一个块中的每个调用,您将看到它完全生成输出。
基本上,你会得到两个i=0
版画,因为你在每个函数调用中都会递归两次。
答案 1 :(得分:2)
您的呼叫按以下顺序执行:
test(2); //initial call; prints "1"
test(1); //test1; prints "0"
test(0); //test1; prints "-1"
test(0); //test2; prints "-1"
test(1); //test2; prints "0"
test(0); //test1; prints "-1"
test(0); //test2; prints "-1"
答案 2 :(得分:1)
整数按值传递,而不是按引用传递。对测试中的i的更改不会影响调用上下文的i。
答案 3 :(得分:1)
这可能会帮助您将其可视化。连字符的数量表示该级别的调用深度和输出,其中一个连字符是第一个级别(初始调用),两个表示第二个级别,依此类推。
->i=1
->test1
-->i=0
-->test1
--->i=-1
-->test2
--->i=-1
->test2
-->i=0
-->test1
--->i=-1
-->test2
--->i=-1
同样出于调试目的,请考虑在递归时跟踪深度,这样可以很好地标记输出。
public static void test(int i, int depth) {
i--;
// ...
test(i, depth++);
}
答案 4 :(得分:0)
对test
的每次调用都有自己的i
。
答案 5 :(得分:0)
Java按值传递参数,而不是通过引用传递参数。根据你传入的内容考虑你的函数调用。像这样:
主要电话:
test(2);
在功能中,你递减i,使其为1,然后调用它:
test(i); // This is equivalent to calling test(1)
test(i); // This is equivalent to calling test(1) again.
所以你的递归函数只是重复,并显示后续值0,-1,-1 - 只显示两次。
答案 6 :(得分:0)
public class Test
{
public static void main(String[] args)
{
test(2); // #1
}
public static void test(int i)
{
i--; // #2 i = 2 -> 1 #7 i = 1 -> 0 #12 i = 0 -> -1 #18 i = 0 -> -1 #24 i = 1 -> 0 #29 i = 0 -> -1 #35 i = 0 -> -1
System.out.println("i="+i); // #3 i = 1 #8 i = 0 #13 i = -1 #19 i = -1 #25 i = 0 #30 i = -1 #36 i = -1
if (i < 0) // #4 i = 1 #9 i = 0 #14 i = -1 #20 i = -1 #26 i = 0 #31 i = -1 #37 i = -1
return; // #15 i = -1 #21 i = -1 #32 i = -1 #38 i = -1
System.out.println("test1"); // #5 i = 1 #10 i = 0 #27 i = 0
test(i); // #6 i = 1 #11 i = 0 #28 i = 0
System.out.println("test2"); // #16 i = 0 #22 i = 1 #33 i = 0
test(i); // #17 i = 0 #23 i = 1 #34 i = 0
}
}
<强>输出:强>
i=1 // #3
test1 // #5
i=0 // #8
test1 // #10
i=-1 // #13
test2 // #16
i=-1 // #19
test2 // #22
i=0 // #25
test1 // #27
i=-1 // #30
test2 // #34
i=-1 // #36