【问题标题】:Java endless recursion and StackOverflowErrorJava 无限递归和 StackOverflowError
【发布时间】:2011-02-01 07:10:02
【问题描述】:

抱歉,可能是一个愚蠢的问题,我是 Java 新手。

有没有办法在 Java 中进行无限递归,类似于:

public void sillyMethod()
{
    System.out.println(i);
    i++;
    sillyMethod();

}

它会抛出 StackOverflowError,但我真的很想无休止地运行它。有什么办法吗?

谢谢!

【问题讨论】:

  • 如果你真的想要“无尽”,那就去迭代吧。
  • 阅读Stack Overflows,你会发现你做不到
  • @Anon 迭代?这不会是无止境的,不是吗?我的意思是,这就是迭代的全部意义所在,你计算一些东西
  • @Sean:我使用迭代基本上是循环的同义词。此外,仅仅因为你在数数并不意味着你永远停止...for(i = 0; ; i++) ; 以任何语言永远循环,溢出时无声环绕。

标签: java recursion stack-overflow


【解决方案1】:

是也不是,(但大多不是!:)

不,这是不可能的(最明智的答案):
对于每次调用,都会有一条激活记录被推送到 JVM 调用堆栈上。这需要非零内存量,因此您会在某个时候耗尽内存,此时会抛出 StackOverflowException。

是的,有可能(超理论答案):
Java 语言规范中没有任何内容明确规定您最终应该遇到 StackOverflowException。这意味着如果你找到一个足够切割的编译器,它可能足够聪明,可以将它编译成一个循环


一个相关的问题是,"Does the JVM support tail-call optimization." 这个问题的答案是,“不,目前没有,但不排除未来版本”。

【讨论】:

  • ...那么激活记录会稍微大一些。但是如果递归可以转化为循环,那又有什么关系呢?
  • "...足够聪明的编译器..." Java 中真正的技术挑战是以不破坏 Java 安全模型的方式实现尾调用优化,等等
  • @Stephen C,你能举个例子说明它与安全模型的关系吗?
【解决方案2】:

正如上面其他人所说,无限递归最终会导致堆栈溢出,至少就 JVM 实现而言。

您可以执行类似的操作,这与此类似,但通过在旧线程死亡之前生成一个新线程来避免堆栈扩展。

public class SillyClass implements Runnable {

private final int count;

public SillyClass(int cnt) {
    this.count = cnt;
}

public static void main(String[] args) {
    Thread t = new Thread(new SillyClass(0));
    t.start();
}

@Override
public void run() {
    System.out.println(count);
    Thread t = new Thread(new SillyClass(count + 1));
    t.start();
}

}

【讨论】:

    【解决方案3】:

    不是递归的,不。它确实意味着创建一个不断增加的调用堆栈,最终您将耗尽内存来容纳它。

    【讨论】:

      【解决方案4】:

      使用 Java,您无法做到这一点。但是,语言中的尾调用优化(尤其是 Ocaml 等函数式语言),您可以这样做,因为它在内部将其变成了循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-12
        • 1970-01-01
        • 1970-01-01
        • 2014-02-03
        • 2016-09-29
        • 2012-10-21
        相关资源
        最近更新 更多