关于try-catch-finally的用法我就不多说了。网上搜一下,资料很多。

这里我想主要讨论下在finally块加入return语句屏蔽异常的问题。

我们先来看这样一段代码,


代码1

 

  1. public class FinallyTest {   
  2.     public static void main(String[] args) {   
  3.         new FinallyTest().print();   
  4.     }   
  5.     public void print() {   
  6.         int i = -1;   
  7.         try {   
  8.             Thread.sleep(1);   
  9.             i = 1 / 0;   
  10.         } catch (Exception e) {   
  11.             System.out.println("at catch block step 1.");   
  12.             throw e;   
  13.         } finally {   
  14.             System.out.println("at finally block i = " + i);   
  15.         }   
  16.     }   
  17. }  

public class FinallyTest { public static void main(String[] args) { new FinallyTest().print(); } public void print() { int i = -1; try { Thread.sleep(1); i = 1 / 0; } catch (Exception e) { System.out.println("at catch block step 1."); throw e; } finally { System.out.println("at finally block i = " + i); } } }

 

 

以上代码在Eclipse里是不会编译通过的,因为在catch块中throw了一个异常,而print方法并没有声明要抛出异常。


现在我们修改代码,让它能够通过编译,代码2

 

  1. public class FinallyTest {   
  2.     public static void main(String[] args) throws Exception {   
  3.         new FinallyTest().print();   
  4.     }   
  5.     public void print() throws Exception {   
  6. …  

public class FinallyTest { public static void main(String[] args) throws Exception { new FinallyTest().print(); } public void print() throws Exception { …

 

就是在printmain方法后加throws Exception,然后运行,看运行结果:

 

  1. at catch block step 1.   
  2. at finally block i = -1  
  3. Exception in thread "main" java.lang.ArithmeticException: / by zero   
  4.     at wxhx.csdn2.FinallyTest.print(FinallyTest.java:12)   
  5.     at wxhx.csdn2.FinallyTest.main(FinallyTest.java:5)  

at catch block step 1. at finally block i = -1 Exception in thread "main" java.lang.ArithmeticException: / by zero at wxhx.csdn2.FinallyTest.print(FinallyTest.java:12) at wxhx.csdn2.FinallyTest.main(FinallyTest.java:5)

 

 

程序先是走到了catch块的第一句,打印了at catch block step 1.

但并没有紧接着去throw e即没有立刻抛出这个异常,之所以这样说,是因为异常的信息是在finally块的打印信息之后才打印的。

这个例子告诉我们,finally不管出异常与否,都必行的代(如果中途终止了jvm,就不必去执行了)

那么何时执行finally块中的代码呢?

在这个例子中,try块中有异常抛出,所以finally块中的代码是在执行了catch语句之后、退出方法之前被执行的 (如果这里执行了throw e,则方法就退出了)


 

下面再看另外一个代码,代码3

 

  1. public class FinallyTest {   
  2.     public static void main(String[] args) {   
  3.         new FinallyTest().print();   
  4.     }   
  5.     public void print() {   
  6.         int i = -1;   
  7.         try {   
  8.             Thread.sleep(1);   
  9.             i = 1 / 0;   
  10.         } catch (Exception e) {   
  11.             System.out.println("at catch block step 1.");   
  12.             throw e;   
  13.         } finally {   
  14.             System.out.println("at finally block i = " + i);   
  15.             return;   
  16.         }   
  17.     }   
  18. }  

public class FinallyTest { public static void main(String[] args) { new FinallyTest().print(); } public void print() { int i = -1; try { Thread.sleep(1); i = 1 / 0; } catch (Exception e) { System.out.println("at catch block step 1."); throw e; } finally { System.out.println("at finally block i = " + i); return; } } }

 

 

这段代码与之前相比,在finally块中增加了return语句

虽然在catch块中有throw e语句,但在print方法后并不用声明throws Exception,也可以通过编译。

因为在try块中有Thread.sleep(1);语句,所以必须要捕获InterruptedException,但在这种情况下,即使我们把catch块去掉了,也不会有问题,这是怎么回事呢?

因为在finally块中的return语句屏蔽了异常。

经过代码2我们已经知道了,异常在finally块被执行之前,虽然会执行catch块中的代码,但并不会退出方法,在退出方法之前,会转向finally块中执行,而在finally块中又恰好有return语句,所以方法就正常退出了,在try块中产生的异常就不会有机会被抛出。