查看此Scala代码:
def rec(n: Int) {
if (n > 1) {
val d = n / 2
rec(d)
// if (d > 1) // abort loop
rec(n/d)
}
}
此代码将导致无限循环。由于尾递归优化,我没有得到StackOverflowError。
用jad编译我得到了这个Java代码:
public void rec(int n)
{
int d;
for(; n > 1; n /= d)
{
int i = n;
d = i / 2;
rec(d);
}
}
在循环的最后一行,该方法调用自身,因此我不理解尾调用位置。有谁可以解释这个?
答案 0 :(得分:9)
rec(d)
的情况下没有尾调用。对于rec(N)
(其中N > 1
)堆栈在log2(N)
调用后不再增长(因为此后n
永远等于2或3,d
是1)。之后,它只是无限循环,内部rec(1)
调用,每次都会立即返回。这就是没有堆栈溢出的原因。
答案 1 :(得分:3)
在您的方法的递归形式中,您有两个递归调用。 StackOverflowError
是由最后一个引起的。
由于尾递归优化,最后一次调用变为循环(第一次调用保持递归),因此你有无限循环而不是无限递归,并且StackOverflowError
不会发生。