【问题标题】:Recursion program has a StackOverflowError with a sample method [duplicate]递归程序有一个带有示例方法的 StackOverflowError [重复]
【发布时间】:2018-09-01 15:21:01
【问题描述】:

我创建了一个递归程序来打印一条消息 Hello 几次,但在编译中出现 StackOverflowError 失败。

package com.recre;

public class Recursionhello {
    static void p() {
        System.out.println("Hello");
    p();
}

public static void main(String[] args) {
    p();
    }
}

它正在打印输出“Hello”几次,然后它正在打印以下错误消息。

输出 -

Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Exception in thread "main" java.lang.StackOverflowError
 at java.io.FileOutputStream.write(Unknown Source)
 at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
 at java.io.BufferedOutputStream.flush(Unknown Source)
 at java.io.PrintStream.write(Unknown Source)
 at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
 at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
 at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
 at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
 at java.io.PrintStream.write(Unknown Source)
 at java.io.PrintStream.print(Unknown Source)
 at java.io.PrintStream.println(Unknown Source)
 at com.recre.Recursionhello.p(Recursionhello.java:5)
 at com.recre.Recursionhello.p(Recursionhello.java:6)
 at com.recre.Recursionhello.p(Recursionhello.java:6)
 at com.recre.Recursionhello.p(Recursionhello.java:6)
 at com.recre.Recursionhello.p(Recursionhello.java:6)
 at com.recre.Recursionhello.p(Recursionhello.java:6)
 at com.recre.Recursionhello.p(Recursionhello.java:6)
 at com.recre.Recursionhello.p(Recursionhello.java:

这里我需要关于错误的助手和一些关于递归的解释。

【问题讨论】:

  • 任何递归方法都必须有终止条件。否则,它只会运行直到堆栈溢出。递归调用的期望终止条件是什么?
  • 这不一定是真的。 OP 写的内容是初学者编写无限循环的一种非常自然的方式。与whilefor 循环相比,它编写起来简单得多,理解起来也简单得多,并且使用的概念更少,并且不需要突变。而且由于它是尾调用,更具体地说,是尾递归调用,它应该在恒定空间中运行,实际上在许多编程语言(例如 Scala、Scheme、 Erlang、Haskell、Racket、F♯、ML)。实际上,问题在于 Java 没有正确的尾调用或至少没有正确的尾递归。
  • @JörgWMittag,虽然你说的是真的,但我在提出的 print “几次”问题中的陈述表明这不是试图编写一个无限循环。

标签: java recursion error-handling stack-overflow


【解决方案1】:

基本上,递归是一种方法调用自身产生循环的方式。任何循环都需要一个条件来终止。在这种情况下,您缺少终止此循环的条件。关于堆栈溢出错误,当您调用一个方法时,它会加载到堆栈上,并且堆栈限制为 256 KB。每个方法调用都会消耗堆栈上的一些内存,当堆栈的大小已满时,我们再次尝试通过调用自身来在堆栈上加载另一个方法,我们会得到 StackOverflowError。

【讨论】:

    【解决方案2】:

    Java 中的任何递归程序都必须有退出条件,如下所示:

    public class Recursionhello {
        static void p(int times) {
            System.out.println("Hello");
            if(times > 0) {
                p(times - 1);
            }
        }
    
        public static void main(String[] args) {
            p(5);
        }
    }
    

    【讨论】:

    • 这不一定是真的。 OP 所写的内容是初学者编写无限循环的一种非常自然的方式。与whilefor 循环相比,它编写起来简单得多,理解起来也简单得多,并且使用的概念更少,并且不需要突变。而且由于它是尾调用,更具体地说,是尾递归调用,它应该在恒定空间中运行,实际上在许多编程语言(例如 Scala、Scheme、 Erlang、Haskell、Racket、F♯、ML)。实际上,问题在于 Java 没有正确的尾调用或至少没有正确的尾递归。
    • @Max 不带参数上述方法的堆栈大小是多少?
    • @suvethaganganes,首先没关系,因为你的程序有缺陷,应该修复。第二:尝试谷歌。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-06
    • 1970-01-01
    • 2013-02-25
    • 2014-07-07
    • 2021-04-08
    • 2022-01-05
    • 2021-03-22
    相关资源
    最近更新 更多