在 try-catch 中来自无限递归的令人困惑的输出

2022-08-31 19:55:15

请考虑以下代码。

public class Action {
private static int i=1;
public static void main(String[] args) {
    try{
        System.out.println(i);
        i++;
        main(args);
    }catch (StackOverflowError e){
        System.out.println(i);
        i++;
        main(args);
    }
 }

}

我正在正确地获得价值。捕获输出后,按如下方式接线。4338StackOverflowError

4336
4337
4338 // up to this point out put can understand 
433943394339 // 4339 repeating thrice  
434043404340
4341
434243424342
434343434343
4344
4345
434643464346
434743474347
4348
434943494349
435043504350

在这里考虑现场演示。它工作正常,直到 。这到底是怎么回事呢?i=4330

仅供参考:

我按照代码做了操作,以了解这里发生了什么。

public class Action {

    private static int i = 1;
    private static BufferedWriter bw;

    static {
        try {
            bw = new BufferedWriter(new FileWriter("D:\\sample.txt"));
        } catch (IOException e) {
           e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        bw.append(String.valueOf(i)+" ");
        try {
            i++;
            main(args);
        } catch (StackOverflowError e) {
            bw.append(String.valueOf(i)+" ");
            i++;
            main(args);
        }
    }

}

现在上一个问题不存在了。现在的值最高校正和运行进一步。我正在跳跃,这可能会运行到(整数的最大值)的值,而不会出现问题。i16824744i=2,147,483,647

存在一些问题。下面也有类似的答案。但是为什么?println()

实际原因是什么?


答案 1

请注意,中缺少换行符。它表示 内部发生了一些错误。433943394339System.out.println()

这里的关键点是需要一些堆栈空间才能工作,因此这是从 中抛出的。System.out.println()StackOverflowErrorSystem.out.println()

这是带有标记点的代码:

public static void main(String[] args) {
    try{
        System.out.println(i); // (1)
        i++;
        main(args); // (2)
    }catch (StackOverflowError e){
        System.out.println(i); // (3)
        i++;
        main(args); // (4)
    }
}

让我们想象一下,当 i = 时,递归级别 N 会发生什么:4338

  • 语句 (1) 在 N 级打印。输出 4338\n4338
  • i递增为4339
  • 控制流在 (2) 处进入 N + 1 级
  • 级别 N + 1 的语句 (1) 尝试打印 ,但在打印换行符之前抛出一个。输出 43394339System.out.println()StackOverflowError
  • StackOverflowError在级别 N + 1 捕获,语句 (3) 尝试打印并再次失败。输出 43394339
  • 在级别 N 捕获异常。此时有更多的堆栈空间可用,因此语句 (3) 尝试打印并成功(正确打印换行符)。输出 4339\n4339
  • i递增,控制流在 (4) 处再次进入 N + 1 级

在此之后,情况将重复使用 。4340

我不确定为什么有些数字在没有换行符的序列之间打印得更合适,也许它与它使用的内部工作和缓冲区有关。System.out.println()


答案 2

我怀疑正在发生的事情是这样的:

  1. 打印 i
  2. 打印换行符
  3. 增加 i
  4. 进入主
  5. 打印 i
  6. 打印换行符
  7. 增加 i
  8. 进入主
  9. 打印 i
  10. StackOverflow 被抛出(而不是打印换行符)
  11. 返回主,现在在捕获
  12. 打印 i
  13. StackOverflow 再次被抛出(而不是打印换行符)
  14. 返回主,在另一个捕获体中。
  15. 打印 i
  16. 打印换行符(现在不再失败,因为我们高出两个级别)
  17. 输入 main,然后返回到 1。

推荐