Try-final-block 可防止 StackOverflowError

看看以下两种方法:

public static void foo() {
    try {
        foo();
    } finally {
        foo();
    }
}

public static void bar() {
    bar();
}

运行显然会导致 ,但运行不会(程序似乎无限期运行)。为什么?bar()StackOverflowErrorfoo()


答案 1

它不会永远运行。每个堆栈溢出都会导致代码移动到 finally 块。问题是,这将需要非常非常长的时间。时间顺序为 O(2^N),其中 N 是最大堆栈深度。

想象一下,最大深度为 5

foo() calls
    foo() calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
    finally calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
finally calls
    foo() calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
    finally calls
       foo() calls
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()
       finally
           foo() calls
              foo() which fails to call foo()
           finally calls
              foo() which fails to call foo()

要将每个级别工作到最终的块中,需要两倍的时间,堆栈深度可能是10,000或更多。如果你每秒可以拨打10,000,000个电话,这将需要10 ^ 3003秒或比宇宙年龄更长。


答案 2

当您从 内部调用中获得异常时,您可以从 中调用并再次开始递归。当这导致另一个异常时,您将从另一个内部调用,依此类推,几乎是无限的foo()tryfoo()finallyfoo()finally()


推荐