抽時間整理了下java中異常與return,以前這塊總是弄混淆,覺得還是寫下來慢慢整理比較好。由於水平有限,僅供參考。廢話不多說,直接上代碼。
下面是兩個方法:
1 public static int throwReturn(){ 2 int ret = 0; 3 try{ 4 ret = 10/0 ; 5 ret++; 6 return ret; 7 }catch(Exception e){ 8 System.out.println("catch block " + e.getMessage()); 9 //ret++; 10 return ret; 11 }finally{ 12 System.out.println("finally block invoked!!!"); 13 ret++; 14 System.out.println("finally block invoked, ret is " + ret); 15 } 16 17 }
1 public static int finallyReturn(){ 2 int ret = 0; 3 try{ 4 ret = 10/0 ; 5 ret++; 6 return ret; 7 }catch(Exception e){ 8 System.out.println("catch block " + e.getMessage()); 9 //ret++; 10 return ret; 11 }finally{ 12 System.out.println("finally block invoked!!!"); 13 ret++; 14 System.out.println("finally block invoked, ret is " + ret); 15 return ret; 16 } 17 18 }
然后在主方法中分別調用兩個方法:
1 public static void main(String args[]){ 2 System.out.println("throwReturn:" + throwReturn()); 3 //System.out.println("finallyReturn:" + finallyReturn()); 4 }
第一個方法輸出結果:
catch block / by zero
finally block invoked!!!
finally block invoked, ret is 1
throwReturn:0
throwRetrun方法返回的結果並不是我預想的1,而是0。
個人分析:
- 程序執行到throwReturn方法的第4行時由於除0而出錯,程序進入catch塊,首先會執行打印輸出:catch block / by zero
- 接下來會執行catch塊的return ret語句,碰到return語句方法會返回退出,而finally語句又是必須執行的,此時程序會將return的結果值暫存起來,繼續執行finally塊。
- 進入finally塊后會輸出:finally block invoked!!! 和finally block invoked, ret is 1
- finally塊執行完成后程序會回到return處,並返回當時暫存的值
第二個方法的輸出結果:
catch block / by zero
finally block invoked!!!
finally block invoked, ret is 1
finallyReturn:1
哎,這次的輸出結果是1了。
仔細比較兩個方法發現第二個方法,在finally語句中多了一個return ret;程序的執行過程同上面基本上是一樣的,只是在最終執行finally代碼塊是碰到了return語句,此時程序就直接將ret的值返回了,而此時ret的值是1,最后輸出:finallyReturn:1
接下來我們再看2個方法:
1 public static int throwException() throws Exception{ 2 int ret = 0; 3 try{ 4 ret = 10/0 ; 5 System.out.println("ret:" + ret); 6 return ret; 7 }catch(Exception e){ 8 System.out.println("catch block " + e.getMessage()); 9 throw e; 10 }finally{ 11 System.out.println("finally block invoked!!!"); 12 ret++; 13 System.out.println("finally block invoked, ret is " + ret); 14 } 15 16 }
1 public static int finallyThrowException() throws Exception{ 2 int ret = 0; 3 try{ 4 ret = 10/0 ; 5 System.out.println("ret:" + ret); 6 return ret; 7 }catch(Exception e){ 8 System.out.println("catch block " + e.getMessage()); 9 throw e; 10 }finally{ 11 System.out.println("finally block invoked!!!"); 12 ret++; 13 System.out.println("finally block invoked, ret is " + ret); 14 return ret; 15 } 16 17 }
然后在主方法中分別調用兩個上面方法:
1 public static void main(String args[]){ 2 try { 3 System.out.println("throwException:" + throwException()); 4 } catch (Exception e) { 5 System.out.println("捕獲到throwException方法拋出的異常," + e.getMessage()); 6 } 7 8 /*try { 9 System.out.println("finallyThrowException:" + finallyThrowException()); 10 } catch (Exception e) { 11 System.out.println("捕獲到finallyThrowException方法拋出的異常," + e.getMessage()); 12 }*/ 13 }
第一個方法輸出結果:
catch block / by zero
finally block invoked!!!
finally block invoked, ret is 1
捕獲到throwException方法拋出的異常,/ by zero
個人分析:
- 在throwException方法執行到第4行時,因為除0操作拋出異常,程序進入catch塊,首先執行打印輸出:catch block / by zero
- 接下來會執行catch塊的throw e語句,向上拋出異常,而finally語句又是必須執行的,此時程序會先執行finally塊。
- 進入finally塊后會輸出:finally block invoked!!! 和finally block invoked, ret is 1
- finally塊執行完成后程序會回到catch塊throw處,將捕獲的異常向上拋出
- 在main方法中會捕獲到throwException方法拋出的異常而進入catch塊,所以會輸出:捕獲到throwException方法拋出的異常,/ by zero
第二個方法的輸出結果:
catch block / by zero
finally block invoked!!!
finally block invoked, ret is 1
finallyThrowException:1
觀察輸出結果會發現,主方法並沒有捕獲到finallyThrowException方法調用時的異常(catch塊的打印沒有執行)。
這兩個方法的主要區別也是在於:在finallyThrowException方法的finally塊中多出了return ret語句。調用finallyThrowException方法的執行過程同調用throwException方法基本一致。
- 在finallyThrowException方法執行時,因為除0操作拋出異常,程序進入catch塊,首先執行打印輸出:catch block / by zero
- 接下來會執行catch塊的throw e語句,向上拋出異常,而finally語句又是必須執行的,此時程序會先執行finally塊。
- 進入finally塊后會輸出:finally block invoked!!! 和finally block invoked, ret is 1
- finally塊執行到return ret時,該方法直接返回了ret的值,
- 在main方法中得到finallyThrowException的返回值后輸出:finallyThrowException:1
從finallyThrowException方法執行結果可以看出方法執行時的異常被丟失了
最后再來看一個小例子
1 public static void finallyWork(){ 2 int count = 0; 3 while(true){ 4 try{ 5 if(count++ == 0){ 6 throw new Exception("my error"); 7 } 8 System.out.println("invoked ..."); 9 }catch(Exception e){ 10 System.out.println("catched exception:" + e.getMessage()); 11 }finally{ 12 System.out.println("finally block invoked!!!"); 13 if(count == 2){ 14 break; 15 } 16 } 17 } 18 }
這個小例子的主要思路是當java中的異常不允許我們回到異常拋出的地點時,我們可以將try塊放到循環里,這樣程序就又可以回到異常的拋出點了,可以同時設置一個計數器,當累積嘗試一定的次數后程序就退出。
ok,就說這么多了,下面附上完整代碼:
package tt; public class FinallyWorks { /** * @param args */ public static void main(String[] args) { //finallyWork(); /* *<output begin> * catch block / by zero * finally block invoked!!! * finally block invoked, ret is 1 * throwReturn:0 *</output end> *從輸出結果中可以看出程序在int temp = 10/0;這一行拋出異常,直接進入catch塊,首先輸出打印catch block...,繼續往下執行時碰到return語句,由於程序 *存在finally語句,在程序返回之前需要執行finally語句。那么此時程序會將return的結果值暫時存起來,繼續執行finally,從輸出上可以看出finally執行后ret *的值變為了1,而整個方法最終的返回結果是0,說明return的是之前暫存的值。 * */ //System.out.println("throwReturn:" + throwReturn()); /* * <output begin> * catch block / by zero * finally block invoked!!! * finally block invoked, ret is 1 * finallyReturn:1 *</output end> *從輸出結果中可以看出程序在int temp = 10/0;這一行拋出異常,直接進入catch塊,首先輸出打印catch block...,繼續往下執行時碰到return語句,由於程序 *存在finally語句,在程序返回之前需要執行finally語句。那么此時程序會將return的結果值暫時存起來,繼續執行finally,從輸出上可以看出finally執行后ret *的值變為了1,有在finally塊中碰到了return語句,方法就直接返回了,所以方法結果返回了1。 * */ //System.out.println("finallyReturn:" + finallyReturn()); /* *<output begin> * catch block / by zero * finally block invoked!!! * finally block invoked, ret is 1 * 捕獲到throwException方法拋出的異常,/ by zero *</output end> *從輸出結果中可以看出在調用throwException方法是出現異常,程序進入該方法的catch塊中,輸出:catch block / by zero *由於存在finally,程序會先執行完finally語句輸出:finally block invoked!!! 和 finally block invoked, ret is 1 *然后將捕獲到的異常拋向上層。上層的main方法catch到這個異常之后會輸出:捕獲到throwException方法拋出的異常,/ by zero *《注意throwException:那句打印是不會輸出的》 * */ /*try { System.out.println("throwException:" + throwException()); } catch (Exception e) { System.out.println("捕獲到throwException方法拋出的異常," + e.getMessage()); }*/ /* *<output begin> * catch block / by zero * finally block invoked!!! * finally block invoked, ret is 1 * finallyThrowException:1 *</output end> *從輸出結果中可以看出在調用finallyThrowException方法是出現異常,程序進入該方法的catch塊中,輸出:catch block / by zero *由於存在finally,程序會先執行完finally語句輸出:finally block invoked!!! 和 finally block invoked, ret is 1 *之后程序執行到finally塊中return語句,直接返回了ret的值,主方法接受到這個返回值后輸出:finallyThrowException:1 *《注意主方法中catch塊代碼並沒有被執行,這就說明了finallyThrowException方法中異常被丟失了》 * */ try { System.out.println("finallyThrowException:" + finallyThrowException()); } catch (Exception e) { System.out.println("捕獲到finallyThrowException方法拋出的異常," + e.getMessage()); } } public static int throwException() throws Exception{ int ret = 0; try{ ret = 10/0 ; System.out.println("ret:" + ret); return ret; }catch(Exception e){ System.out.println("catch block " + e.getMessage()); throw e; }finally{ System.out.println("finally block invoked!!!"); ret++; System.out.println("finally block invoked, ret is " + ret); } } public static int finallyThrowException() throws Exception{ int ret = 0; try{ ret = 10/0 ; System.out.println("ret:" + ret); return ret; }catch(Exception e){ System.out.println("catch block " + e.getMessage()); throw e; }finally{ System.out.println("finally block invoked!!!"); ret++; System.out.println("finally block invoked, ret is " + ret); return ret; } } public static int throwReturn(){ int ret = 0; try{ ret = 10/0 ; ret++; return ret; }catch(Exception e){ System.out.println("catch block " + e.getMessage()); //ret++; return ret; }finally{ System.out.println("finally block invoked!!!"); ret++; System.out.println("finally block invoked, ret is " + ret); } } public static int finallyReturn(){ int ret = 0; try{ ret = 10/0 ; ret++; return ret; }catch(Exception e){ System.out.println("catch block " + e.getMessage()); //ret++; return ret; }finally{ System.out.println("finally block invoked!!!"); ret++; System.out.println("finally block invoked, ret is " + ret); return ret; } } /** * 當java中的異常不允許我們回到異常拋出的地點時,我們可以將try塊放到循環里, * 這樣程序就又可以回到異常的拋出點了,可以同時設置一個計數器, * 當累積嘗試一定的次數后程序就退出。 */ public static void finallyWork(){ int count = 0; while(true){ try{ if(count++ == 0){ throw new Exception("my error"); } System.out.println("invoked ..."); }catch(Exception e){ System.out.println("catched exception:" + e.getMessage()); }finally{ System.out.println("finally block invoked!!!"); if(count == 2){ break; } } } } }