【问题标题】:Confused with try-catch-finally issue? [duplicate]对 try-catch-finally 问题感到困惑? [复制]
【发布时间】:2013-11-06 10:03:32
【问题描述】:

我试图找出try-catch-finallyjava 中的执行顺序。我认为执行顺序应该是

  1. 试试
  2. catch(如果发生错误/捕获异常)
  3. finally(无论是否捕获到异常)

但我对以下结果感到困惑

public class TryCatchFinally {
static int i = 0;
public static void main(String[] args) {
    try {
        System.out.println(i++);
        main(args);
    } catch (StackOverflowError e) {
        System.out.println("Catch");
    } finally {
        System.out.println("Finally");
    }
 }
}

输出(输出的一部分)

9127
9128
9129
9130
CatcFCatch // what is the wrong here???
Finally
Finally // there are more Finally printed here.

我的问题是这里到底发生了什么?

让我补充更多为什么它不打印"Catch"???

当我在IntelliJ IDEA 中运行它时,我得到了这个。但是当我在terminal 中运行时,我的输出如下。

9151
9152
9153
9154CatchFinallyCatch
Finally
Finally
Finally
Finally

【问题讨论】:

  • @MarounMaroun 是的,但我想弄清楚这里到底发生了什么?
  • 您会打印出一堆“Finally”,因为当您完成执行每个递归调用时,堆栈会被解压并且所有 finally 块都会被执行。至于奇怪的“CatcFCatch”,我不确定,但我怀疑这可能是因为System.out.println 在堆栈底部调用时导致更多StackOverflowError 在更高的递归调用中被捕获。
  • This 可能会回答您的问题。
  • @Maroun - 有趣的是,您链接到的问题是由同一个人提出的。
  • @Ruchira:这与您在 8 月份提出的问题差不多相同(由 Maroun Maroun 链接)。

标签: java exception try-catch-finally


【解决方案1】:

您可能会在println 调用中某处 遇到堆栈溢出错误(可能是因为正在进行一些刷新或类似的事情),从而使println 方法处于不一致的状态(具有打印 部分 应该是什么)。

当您已经处理 StackOverflowError 时很容易发生这种情况,因为此时您已经危险地接近溢出堆栈(因为您刚刚从一个堆栈中恢复过来非常接近问题)。

我的解释是这样的:

  • main 经常递归调用自身 ...
  • 您第 9130 次递归调用 main
  • 它会打印那个数字
  • 它第 9131 次调用自己
  • 它尝试打印该数字,但抛出 StackOverflowError,因为堆栈已满
  • 您输入 catch 并尝试打印“Catch”
  • println 调用另一个StackOverflowError 期间发生
  • finally 块被执行,因为catch 块完成(突然)
  • 它尝试打印“Finally”
  • println打电话另一个StackOverflowError发生
  • StackOverflowErrormain 的第 9130 次调用中被捕获
  • 它打印“Catch”(成功,因为堆栈现在短了 1 个元素!)
  • finally 块已执行并成功打印 Finally,因为堆栈现在短了 1 个元素。
  • 更多 finally 块执行。

【讨论】:

  • 我认为 OP 在println 中发现了堆栈溢出,他使用的是什么版本的 Java?
  • @0x90 并不真正相关,我认为。在println 内部,有大量的方法调用,其中任何一个都可能触发堆栈溢出。这适用于 Java API 的许多方法。这不是一个真正的错误。这就是事情的运作方式。
【解决方案2】:

这是因为对 main 的递归调用。因此,当您在 main 中调用 main 时,您将多次输入 try catch 块,并且您从它返回的次数与您在第一次 StackOverflow 发生后输入它的次数相同。这就是多次决赛的原因。

编辑: 当我看到一些不赞成的投票时,没有任何合理的解释,如果有人认为我错了,只需在 finally 块中打印该死的 i 计数器并减少。

public static void main(String[] args) {
    try {
        System.out.println(i++);
        main(args);
    } catch (StackOverflowError e) {
        System.out.println("Catch");
    } finally {
        System.out.println("Finally: "+ (i--));
    }
 }

【讨论】:

  • 为什么不每次都抓到??
  • 因为异常不会向上传播(不会重新抛出)。没有任何 cmets,我不明白反对票。
  • 我不会投反对票,但我认为这是因为你没有解释有趣的 catch 输出。
  • 没错,我专注于多次 finally 处决。
【解决方案3】:

您是否使用了 IDE(eclipse 或类似的),如果是,则可能是由于这个原因。

这是我尝试的结果 -

// 代码

public static void main(String[] args) throws IOException {

    File file = new File("resources/ouput.txt");
    file.createNewFile();
    PrintStream printStream = new PrintStream(file);
    System.setOut(printStream);

    overflowTester(0);

}

private static void overflowTester(int index) {
    try {
        System.out.println(index++);
        overflowTester(index);
    } catch (StackOverflowError  e) {
        System.out.println("Catch");
    } finally {
        System.out.println("Finally");
    }
}

// 输出

0
1
2
3
4
5
6
7
8
9
10
...
...
...
9666
Catch
Finally
...
...
Finally

注意:'9666' 打印在第 9667 行,最后一个 finally 在第 19336 行。

就我而言,运行以下程序:

private static int index = 0;

public static void main(String[] args) throws IOException {

    try {
        System.out.println(index++);
        main(args);
    } catch (StackOverflowError  e) {
        System.out.println("Catch");
    } finally {
        System.out.println("Finally");
    }

}

从命令提示符中,产生了类似的结果:

0
1
2
3
4
5
...
...
9667
Catch
Finally
...
...
Finally

“9667”打印在第 9668 行,最后一个“Finally”打印在第 19338 行。

【讨论】:

    猜你喜欢
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-01
    • 2016-12-12
    • 2014-10-03
    • 1970-01-01
    • 2014-06-01
    相关资源
    最近更新 更多