java try没有catch 在catch和finally子句中抛出异常




try catch runtimeexception (8)

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("TryA L1\n");
            q();
            System.out.print("TryB L1\n");
        }
        catch (Exception i) {
            System.out.print("Catch L1\n");                
        }
        finally {
            System.out.print("Finally L1\n");
            throw new MyExc1();
        }
    }

    static void q() throws Exception {
        try {
            System.out.print("TryA L2\n");
            q2();
            System.out.print("TryB L2\n");
        }
        catch (Exception y) {
            System.out.print("Catch L2\n");
            throw new MyExc2();  
        }
        finally {
            System.out.print("Finally L2\n");
            throw new Exception();
        }
    }

    static void q2() throws Exception {
        throw new MyExc1();
    }
}

订购:

TryA L1
TryA L2
Catch L2
Finally L2
Catch L1
Finally L1        
Exception in thread "main" MyExc1 at C1.main(C1.java:30)

https://www.compilejava.net/

在大学的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();
        }
    }
}

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


即使在try / catch块中的任何位置引发异常,finally子句也会执行。

因为这是最后一次在main执行并引发异常,这是调用者看到的异常。

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


这就是Wikipedia关于finally子句所说的:

更常见的是一个相关的子句(最后,或确保)执行是否发生异常,通常是释放在异常处理块体内获取的资源。

我们来剖析你的程序。

try {
    System.out.print(1);
    q();
}

所以, 1会输出到屏幕上,然后调用q() 。 在q() ,抛出异常。 异常然后由Exception y捕获,但它什么都不做。 然后执行finally子句(它必须),所以, 3将被打印到屏幕上。 因为(在方法q()存在finally子句中抛出的异常,所以q()方法将异常传递给父堆栈(通过在方法声明中throws Exceptionnew Exception()将被抛出并被catch ( Exception i )MyExc2异常将被抛出(现在将其添加到异常堆栈中),但最终将main块中执行。

所以在,

catch ( Exception i ) {
    throw( new MyExc2() );
} 
finally {
    System.out.print(2);
    throw( new MyExc1() );
}

一个finally子句被调用...(记住,我们刚刚捕获了Exception i和抛出的MyExc2 ), 2被打印在屏幕上......并且在屏幕上打印2之后,引发MyExc1异常。 MyExc1public static void main(...)方法处理。

输出:

“主线程MyExc1中的132Exception”

讲师是正确的! :-)

实质上 ,如果你在try / catch子句中有一个finally ,那么finally将被执行( 捕获异常之前捕获异常)


众所周知,finally代码块在try和catch之后执行并始终执行....但是,正如你所看到的那样有点棘手,有时候请查看下面的代码片段,你会发现返回和throw语句不会不要总是按照我们期望的主题顺序去做他们应该做的事情。

干杯。

/////////////Return dont always return///////

try{

    return "In Try";

}

finally{

    return "In Finally";

}

////////////////////////////////////////////


////////////////////////////////////////////    
while(true) { 

    try {

        return "In try";

   } 

   finally{

        break;     

    }          
}              
return "Out of try";      
///////////////////////////////////////////


///////////////////////////////////////////////////

while (true) {     

    try {            

        return "In try";    

     } 
     finally {   

         continue;  

     }                         
}
//////////////////////////////////////////////////

/////////////////Throw dont always throw/////////

try {

    throw new RuntimeException();

} 
finally {

    return "Ouuuups no throw!";

}
////////////////////////////////////////////////// 

我想你只需要走finally街区:

  1. 打印“1”。
  2. finallyq打印“3”。
  3. finallymain打印“2”。

在阅读你的答案并看到你是如何想出答案的基础上,我相信你认为“进行中的例外”具有“优先”。 记住:

当一个新的异常抛出一个catch块或最后一个将从该块传出的块时,那么当新异常向外传播时,当前异常将被中止(并且被遗忘)。 新的异常开始展开堆栈,就像任何其他异常一样,从当前块(catch或finally块)中退出,并且一直沿用任何适用的catch或finally块。

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

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

现在回想一下执行过程,记住每当你点击throw ,你应该中止跟踪当前的异常并开始追踪新的异常。


引用JLS 9:14.20.2。 执行try-finally和try-catch-finally

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

  • 如果finally块正常完成,则由于原因R,try语句突然完成。

  • 如果由于S原因,finally块突然完成,那么try语句为S原因突然完成(并且原因R被丢弃)。


一个method不能同时throw两个异常。 它总是会抛出最后抛出的exception ,在这种情况下,它将始终是finally块中的exception

当方法q()的第一个异常被抛出时,它将被catch'ed,然后被finally块抛出的异常吞噬。

q() - >抛出new Exception - > main catch Exception - > throw new Exception - > finally抛出一个新的exception (和catch的一个是“失去”)





exception-handling