在递归状态中,java如何存储过去的值?

在递归状态中,java如何存储过去的值?,java,recursion,Java,Recursion,我知道这个方法的输出是 public class Factorial { int factR(int n){ int result; if(n==1)return 1; result=factR(n-1)*n; System.out.println("Recursion"+result); return result; } 然而,我的问题是java如何存储阶乘的过去值?它还表现为java决定自下而上乘以这些值。发生这种情况的过程是什么?这是由于java如

我知道这个方法的输出是

public class Factorial {
int factR(int n){
    int result;
    if(n==1)return 1;
    result=factR(n-1)*n;
    System.out.println("Recursion"+result);
    return result;
}
然而,我的问题是java如何存储阶乘的过去值?它还表现为java决定自下而上乘以这些值。发生这种情况的过程是什么?这是由于java如何在堆栈中存储内存造成的?

这些值存储在Java的调用堆栈中。相反,因为递归函数是如何定义的。得到n,然后乘以n-1的同一个函数的值,依此类推,直到它达到1,然后在该级别返回1。因此,对于5,它将是5*4*3*2*1。无论乘法的方向如何,答案都是一样的

您可以通过编写一个程序来了解它是如何工作的,该程序将破坏堆栈并提供StackOverflowerError。不能在调用堆栈上存储无限状态

  Recursion2
  Recursion6
  Recursion24
  Recursion120
  Recursive120

我想了解你

如果有人也这么叫

factR(3)
这是一个递归过程,显然java使用堆栈来维护工作流程

注:请参见下面的程序性任务,并再次注意 当前任务完成后返回的位置


它实际上根本不存储“过去的值”。它将程序的状态存储在堆栈中,每个方法调用都有一个帧,其中包含诸如程序所在的当前行之类的数据。但是对于堆栈顶部的当前方法,变量
result
在任何时候都只有一个值。它返回并用于在调用此函数的帧中计算
结果
,依此类推,因此出现了自底向上的行为

一种减少混淆的方法是暂时取消递归。假设Java不支持递归,只允许方法调用其他不同的方法。如果您仍想采用类似的方法,一种粗略的方法是将
factR
方法复制粘贴到多个不同但类似的方法中,例如:

result=factR(2)*3 // again call where n=2
    -> result=factR(1)*2 // again call where n=1
            -> now n=1 so that it will return 1

    -> result=1*2 // after return it will become 6
       print "Recursion2" // print remaning stuff
       return 2;
result=2*3 // after return it will become 6
print "Recursion3" // print remaning stuff
return 3    

类似地,定义一个调用
fact3
fact2
,尽管最终您不得不停止定义新方法,只希望最后一个方法不会被调用。这将是一个可怕的程序,但它应该是非常明显的工作原理,因为没有什么神奇的。经过一些思考,你可以意识到,
factR
基本上是在做同样的事情。然后,您可以看到Java并没有“决定”自下而上乘以值:观察到的行为是给定代码的唯一逻辑可能性。

Java将阶乘的过去值存储在堆栈中
,而且是您选择在返回之前打印(“自下而上”),而不是Java。我建议您在调试器中逐步执行此代码。这将显示执行流以及调用堆栈中的所有值。当你有一个程序,但你不明白它在做什么时,你应该首先尝试IDE中的调试器。明白了吗?对于每个递归过程,java会在递归结束之前将所有值存储在堆栈中吗?如果你编写一个递归函数,保持无限嵌套,那么你会得到一个StackOverflower错误,因此,此网站的名称:)正是如此。这是它应该有的。如果你没有,为什么你会得到一个StackOverflower错误。换句话说,堆栈上的内容太多,它就会溢出。这就是这种无限递归在堆栈上存储无限值时出错的地方。这里提到这一点是为了说明值不能无限地存储在堆栈上。如果您需要了解它,您可以查看以下内容:
result=factR(2)*3 // again call where n=2
    -> result=factR(1)*2 // again call where n=1
            -> now n=1 so that it will return 1

    -> result=1*2 // after return it will become 6
       print "Recursion2" // print remaning stuff
       return 2;
result=2*3 // after return it will become 6
print "Recursion3" // print remaning stuff
return 3    
int fact1(int n){
    int result;
    if(n==1)return 1;

    // Here's the difference: call the 'next' method
    result=fact2(n-1)*n;

    System.out.println("Recursion"+result);
    return result;
}