首先,您正在阴影化您的
args
变量。在您的字段中定义的
args
不会被视为您尝试在
main
中递归调用的相同
args
。
其次,递归最终会耗尽内存,但这取决于您为应用程序分配了多少内存以及此时内存中还有什么。如果您给它2GB(或更多)的空间来处理,递归仍将耗尽 - 但可能在更高的值处运行。
例如,当我使用
-Xmx6G
运行时,我得到的就是这个:
10791
10796
10789
由于我的操作系统正在运行其他程序,因此数字可能会有所不同。
现在,关于它耗尽的
原因:你的调用被放置在一个栈中,这不是内存中的有限空间;它可以(有时会)用完。
每次在Java中调用函数时,它都会进入堆栈。
First time through:
> main(0)
main()
总是被调用,因此它总是在栈的底部。
如果我们再次调用main()
,那么它的另一个调用将被放置在堆栈上:
Second time through:
> main(1)
> main(0)
对于大多数简单应用程序,只有少量调用(不到100个)被放入调用栈中,它们的生命周期很短,因此它们不会在调用栈上持续很长时间。
然而,由于缺乏称为“基本情况”的东西,您的应用程序与众不同。这是您用来决定停止递归的方法。
例如,以著名的阶乘函数为例,该函数陈述如下:
{ 1 if n = 0
n! = <
{ n * (n-1)! if n > 0
我们有一个基本情况:如果
n = 0
,那么我们不会继续递归下去。否则,我们就继续前进。
以下是代码示例:
public long factorial(int n) {
return n == 0 ? 1L : n * factorial(n-1);
}
一旦到达我的基本情况,我就停止添加调用堆栈 - 我实际上开始解决它们。
这是一个 factorial(4)
的示例:
> factorial(4)
> factorial(3)
> factorial(2)
> factorial(1)
> factorial(0)
> 1
> 1 * 1
> 1 * 1 * 2
> 1 * 1 * 2 * 3
> 1 * 1 * 2 * 3 * 4
所以,这就是说:如果你要做一个递归函数,
确保递归可以结束。否则,你会一直遇到这个问题。