Java 这个递归循环代码是如何执行的
我有一些代码行,我无法理解代码是如何执行的,我指的是程序流 代码: 我认为输出应该是:0 但输出为:0,0,1 我做过很多次以上的调试, 我在调试时看到的流程:Java 这个递归循环代码是如何执行的,java,recursion,Java,Recursion,我有一些代码行,我无法理解代码是如何执行的,我指的是程序流 代码: 我认为输出应该是:0 但输出为:0,0,1 我做过很多次以上的调试, 我在调试时看到的流程: 从第3行开始执行,即以2作为参数调用printit() 第6行,如果条件检查nvalue(如果大于零),则控制转到第7行,即prinit()再次通过递减n值进行调用 步骤2:继续执行,直到n值变为0,如果条件为false,则执行第6行。所以在第9行,SYSO打印0 然后,无法理解,控件如何再次从第10行转到第5行?? 在第一次调用时,n
n
value(如果大于零),则控制转到第7行,即prinit()再次通过递减n值进行调用在第一次调用时,
n
为2
if(n>0){ // 2, note this is an if - not a while loop.
printit(--n); // recurses, after this n = 1; references won't update by the recursion.
// Well, not with primitives or immutable types anyway.
// n = printit(n - 1); // <-- This would behave like you seem to expect.
// n = printit(--n); // <-- and so would this, but not in C!
}
System.out.print(n+","); // prints 1 !!!!
return n; // <- returns 1
if(n>0){//2,注意这是一个if-not-while循环。
printit(--n);//递归,在此n=1之后;引用不会通过递归更新。
//好吧,不管怎样,不是使用原语或不可变类型。
//n=printit(n-1);//让我用调试模式一步一步地解释一下
请在调试模式下自下而上查看方法堆栈。
因为它是一个递归方法,在n>0
之前都是自己调用的。这意味着这个方法有三个调用,如下所示
现在它将返回值并从方法堆栈中返回,如下面的快照所示
最后,它将返回到调用它的main
方法
由于此方法被调用了三次,因此您得到的是0,0,1,
不要考虑递归方法调用,而是首先考虑任何方法调用。例如,如果您在main中调用一个方法,程序执行将转到该方法并执行该方法中的所有代码。一旦该方法执行完毕,程序流将返回返回main并继续执行main中的代码行。这同样适用于递归调用
在第一次使用2运行时,2大于0。因此,将2减为1,然后调用printIt(1)
。这意味着程序调用的函数运行完毕后将返回此处。但由于printIt()是递归的,因此下一次调用还将等待其内部的任何方法调用
因此,在下一次调用中,n现在是1,大于0。您将其递减为0,然后调用printIt(0)
。当此事件运行时,它未通过if(n>0)
检查,并继续到第9行打印0,然后返回
既然完成了,程序将返回到第二次调用printIt()
。记住,在这次调用中,n是0。它现在可以继续自己的第9行并打印0。然后,这将重复到原来对打印1的printIt()
的调用
因此,当所有的操作都完成后,您将得到0,0,1。在这个程序中,printit()
调用了三次
控件如何再次从第10行转到第5行
以下是控制流程:
printit(0)
--n=0
,打印“0,
,返回0
printit(1)
--n=1
,打印“0,
,返回0
printit(2)
--n=2
,打印“1,
,返回1
main()
因此输出为:0,0,1,
为了更好地理解,在调试时在return语句中放置断点
以下是控制/内存流程图:
编辑1:或者图像解释:
尝试使用调试器跟踪每个函数中的“n”值。缺少的一件事是:在第7行中对printit()的递归调用完成后,将执行函数的其余部分。每次调用printit()时
在递归调用完成后打印输出,因此它基本上会在递归的“退出”过程中打印三个输出。这就是为什么输出是三个值的集合,而不是像您所期望的那样只有一个值。您正在调用printit()请详细说明这一行:return n;//因为2-1是一个。执行线程从递归返回,现在如果您有n=printit(-n);
,那么您将获得预期的输出。
if(n>0){ // 2, note this is an if - not a while loop.
printit(--n); // recurses, after this n = 1; references won't update by the recursion.
// Well, not with primitives or immutable types anyway.
// n = printit(n - 1); // <-- This would behave like you seem to expect.
// n = printit(--n); // <-- and so would this, but not in C!
}
System.out.print(n+","); // prints 1 !!!!
return n; // <- returns 1