什么是第一 - 最后还是阻止?

时间:2010-06-24 11:05:13

标签: java

考虑以下测试用例:

public class Main {

    static int a = 0;

    public static void main(String[] args) {
        try {
            test();
            System.out.println("---");
            test2();
        }
        catch(Exception e) {
            System.out.println(a + ": outer catch");
            a++;
        }
    }

    public static void test()
    {
        try {
            throw new Exception();
        }
        catch (Exception e) {
            System.out.println(a + ": inner catch");
            a++;
        }
        finally {
            System.out.println(a + ": finally");
            a++;
        }
    }

    public static void test2() throws Exception
    {
        try {
            throw new Exception();
        }
        finally {
            System.out.println(a + ": finally");
            a++;
        }
    }
}

输出:

0: inner catch
1: finally
---
2: finally
3: outer catch

为什么test()捕获事件发生在最后test2()之前是什么原因解释了?

8 个答案:

答案 0 :(得分:16)

由于try中的test2()块没有catch块,因此只有finally。代码不会“跳回”调用者进入catch,然后“跳到”finally继续前进,就像你想象的那样。

答案 1 :(得分:16)

关键点是:

  • try-(catch)-finally块中,该特定finally块的try最后执行
  • 您可以在另一个中嵌套 try块,并且每个嵌套的try块都可以拥有自己的finally,这些块将在最后执行个人try阻止

所以是的,finally最后执行,但连接到try块。

所以给出以下片段:

try {
    try {
        throw null;
    } finally {
        System.out.println("Finally (inner)");
    }
} catch (Throwable e) {
    System.out.println("Catch (outer)");
}

打印(as seen on ideone.com):

Finally (inner)
Catch (outer)

观察:

  • (inner)内,Finally是最后一次(无论catch是否成功)
  • Catch (outer)跟在Finally (inner)之后,但那是因为Finally (inner)嵌套在 try
  • 中的另一个 (outer)块内

同样,以下代码段:

    try {
        try {
            throw null;
        } catch (Throwable e) {
            System.out.println("Catch (inner)");
        } finally {
            System.out.println("Finally (inner)");
            throw null;
        }
    } catch (Throwable e) {
        System.out.println("Catch (outer)");
    }

打印(as seen on ideone.com):

Catch (inner)
Finally (inner)
Catch (outer)

参考

相关问题

答案 2 :(得分:7)

catch最终出现在同一个try-catch-finally范围之前。

test2在try2的try-catch-finally范围内没有捕获,所以它在离开范围之前完成了最终并落入了更高的捕获。

答案 3 :(得分:4)

因为finally块总是在退出范围之前执行。调用test2()后的事件序列如下:

    test2() 中抛出了
  1. 异常
  2. 由于test2没有catch阻止,因此异常会传播到调用方。
  3. 由于test2finally块,因此会在从方法返回之前执行。
  4. main方法中的catch捕获异常。

答案 4 :(得分:2)

因为, finally 是在try..catch块中执行的最后一个代码,无论是抛出,抛出然后处理,还是根本不抛出异常。

实际上,唯一一次最终将被调用的是JVM在执行它之前是否退出,或者执行try代码的线程是否被终止或被中断。

回应评论: Java Description of finally

Note: If the JVM exits while the try or catch code is being executed,
     

那么finally块可能没有   执行。同样,如果线程   执行try或catch代码是   中断或杀死,终于   即使该块也可能无法执行   申请作为一个整体继续。

但是你是正确的,因为抛出了一个ThreadDeath异常,我找不到太多关于来自sun的冲突信息的细节。这可能是一个问题。

终于(请原谅双关语)@brainimus,如果你在最后并抛出异常,那么最终代码 正在被执行,我的观点是最终代码未执行的条件。

答案 5 :(得分:2)

尝试 - 捕获并最终用于避免程序因执行程序期间发生意外错误而终止程序的情况。

以下几点很重要......

1)一个块只有一次尝试......一个块的任意数量的catch语句,最后只有一个用于一个块的

2)最后是可选的。

3)catch也是可选的,但如果缺少catch语句,则最终必须出现。

4)对应于子例外的所有捕获必须出现在父异常的catch之前。

5)无论异常是否发生,finally块中出现的语句总是以一次排除的方式执行。

即。如果遇到System.out.exit()语句,则程序会立即终止,因此在这种情况下最终无法执行。

注意:即使在try块中出现一个return语句......然后也会执行finally中的代码。

答案 6 :(得分:0)

如果用方法代码替换函数,则得到:

public class Main {

    static int a = 0;

    public static void main(String[] args) {
        try {
            try {
                throw new Exception();
            }
            catch (Exception e) {
                // I catch only the *first* exception thrown   
                System.out.println(a + ": inner catch");
                a++;
                // let's go to the finally block
            }
            finally {
                System.out.println(a + ": finally");
                a++;
                // we go on
            }
            System.out.println("---");
            try {
                throw new Exception();
            }
            finally {
                // executed because at the same level
                System.out.println(a + ": finally");
                a++;
            }
        }
        catch(Exception e) {
            // I catch only the *second* exception thrown
            System.out.println(a + ": outer catch");
            a++;
        }
    }

第一个异常使catch块执行,然后执行第一个finally块。由于第一个捕获块,它在外层看不到。第二个异常是由外层的catch块拦截的,但是最后一个异常位于内层,首先执行。

答案 7 :(得分:0)

首先执行try块。如果try块中存在需要捕获的异常,则执行Catch。最后,无论是否存在异常,都会运行块。如果在try块中有return语句,那么在try块中返回之前,最后块执行,然后在try块中执行return。