catch和finally子句抛出异常

Jub*_*uff 150 java exception-handling exception

关于大学的Java问题,有这段代码:

class MyExc1 extends Exception {}
class MyExc2 extends Exception {}
class MyExc3 extends MyExc2 {}

public class C1 {
    public static void main(String[] args) throws Exception {
        try {
            System.out.print(1);
            q();
        }
        catch (Exception i) {
            throw new MyExc2();
        }
        finally {
            System.out.print(2);
            throw new MyExc1();
        }
    }

    static void q() throws Exception {
        try {
            throw new MyExc1();
        }
        catch (Exception y) {
        }
        finally {
            System.out.print(3);
            throw new Exception();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我被要求提供输出.我回答13Exception in thread main MyExc2,但正确的答案是132Exception in thread main MyExc1.为什么会这样?我只是无法理解MyExc2在哪里.

Ber*_*t F 156

在阅读你的答案并了解你如何提出它的基础上,我相信你认为"正在进行中的异常"具有"优先权".记住:

当一个新的异常被抛出一个catch块或者最后一个将传播出该块的块时,当新的异常向外传播时,当前的异常将被中止(并被遗忘).新异常开始展开堆栈,就像任何其他异常一样,从当前块(catch或finally块)中止,并受到任何适用的catch或finally块的影响.

请注意,适用的catch或finally块包括:

当在catch块中抛出新异常时,新异常仍然受该catch的finally块(如果有)的影响.

现在回溯执行,记住每当你点击时throw,你应该中止跟踪当前的异常并开始跟踪新的异常.

  • «基于阅读你的答案并看到你如何提出它,我相信你认为"正在进行中的异常"具有"优先权"»谢谢......这正是我的想法:) (7认同)

Buh*_*ndi 38

这就是维基百科关于finally子句的说法:

更常见的是一个相关的条款是否发生了异常,通常以释放异常处理块的主体内获得的资源时执行(最终,或确保).

让我们剖析您的计划.

try {
    System.out.print(1);
    q();
}
Run Code Online (Sandbox Code Playgroud)

因此,1将被输出到屏幕,然后q()被调用.在q(),抛出异常.然后捕获异常,Exception y但它什么也没做.甲最后然后子句被执行(它有),所以,3将被打印到屏幕.因为(在方法q()中,finally子句中抛出异常,也会q()将异常传递给父堆栈(通过throws Exception方法声明中)new Exception()将被抛出并被捕获catch ( Exception i ),MyExc2异常将被抛出(现在将其添加到异常堆栈中) ),但最后main块中将首先执行.

所以,在

catch ( Exception i ) {
    throw( new MyExc2() );
} 
finally {
    System.out.print(2);
    throw( new MyExc1() );
}
Run Code Online (Sandbox Code Playgroud)

一个finally子句被称为...(记住,我们刚刚捕获Exception i并抛出MyExc2)本质上2是打印在屏幕上...并且2在屏幕上打印之后,MyExc1抛出异常.MyExc1public static void main(...)方法处理.

输出:

"线程主MyExc1中的132Exception"

讲师是对的!:-)

从本质上说,如果你有一个最终在一个try/catch子句,终于将(执行捕获异常之前抛出捕获的异常出)


Rol*_*and 33

引自JLS 11:14.20.2.执行try-finally和try-catch-finally

如果catch块由于原因R突然完成,则执行finally块.然后有一个选择:

  • 如果finally块正常完成,则try语句突然完成,原因是R.

  • 如果finally块由于原因S而突然完成,则try语句突然完成,原因S(并且原因R被丢弃).

  • 不是丢弃原因 R,而是将原因 R 作为抑制的异常添加到原因 S 中吗? (2认同)

Ale*_*yak 21

即使从try/catch块中的任何地方抛出异常,也会执行finally子句.

因为它是最后一个被执行main并且它抛出异常,这是调用者看到的异常.

因此,确保该finally子句不会抛出任何东西的重要性,因为它可以吞噬try块中的异常.

  • 如果try/catch块中没有抛出异常,它也将被执行 (4认同)
  • +1:直接并且没有蜿蜒的整个堆栈,OP似乎已经理解了这一点. (2认同)

Gar*_*ero 9

A method不能同时有throw两个例外.它将始终抛出最后一次抛出exception,在这种情况下,它将始终是finally块中的一个.

q()抛出方法的第一个异常时,它会被finally块抛出异常捕获然后吞噬.

q()- >抛出new Exception - > main catch Exception - > throw new Exception - > finally抛出一个新的exception(和catch"丢失"中的一个)


yyF*_*red 5

直到打印出来逻辑才清晰13。然后in抛出的异常q()catch (Exception i)in捕获main()并且anew MyEx2()准备好抛出。但是,在抛出异常之前,finally必须先执行该块。然后输出变为132finally要求抛出另一个异常new MyEx1()

由于一个方法不能抛出多个异常Exception,因此它总是会抛出最新的异常Exception。换句话说,如果 和catchfinally都尝试抛出Exception,则Exceptionin catch 会被吞掉finally,并且只会抛出 in 的异常。

因此,在这个程序中,ExceptionMyEx2被吞掉并被MyEx1抛出。这个异常被抛出main()并且不再被捕获,因此JVM停止并且最终的输出是132Exception in thread main MyExc1.

finally本质上,如果在子句中有 a try/catch,则 a将在捕获异常之后在抛出任何捕获的异常之前finally执行,并且最后只会抛出最新的异常