l

2013年11月12日 星期二

Java的try、catch、finally(1):Java SE 7之前

Nov. 06 16:22~17:47

image

 

Java SE 7之前

寫了這麼多篇Java例外處理的文章,只談過checked與unchecked exception的差別,還沒有正式介紹過Java的例外處理機制。鄉民們可能會想:「Java的例外處理不就是try、catch、finally這三個關鍵字就搞定了嗎,有什麼好講的?」如上圖所示,在Java SE 7之前,Java的例外處理的主要框架的確是依靠try、catch、finally來達成。鄉民們可以使用try、catch,try、finally、或是try、catch、finally這三種不同的方式來捕捉與處理例外。這三者的用途分別是:

  • try:如果想要在method裡面捕捉例外,必須要可能發生例外的程式碼放到try block裡面,否則例外只能往外傳遞。
  • catch:catch block一定會跟在try block後面,如果想捕捉try block所發生的例外,就把這個例外的型態寫在catch子句裡面,例如catch(IOException e)就可以捕捉到IOException這種型態的例外。如果想要捕捉多種例外型態,就必須要撰寫多個catch block,例如:
   1: public void try_multiple_catch(){
   2:     try{
   3:         throwIOException();
   4:         throwSQLException();
   5:     }
   6:     catch(IOException e){
   7:     }
   8:     catch(SQLException e){
   9:     }
  10:     catch(Exception e){
  11:       // blanket catch
  12:     }
  13: }


上面程式範例的try block呼叫throwIOException()與throwSQLException()這兩個method,他們分別會丟出IOException與SQLException。為了捕捉這兩個例外,需要寫兩個catch block(6~9行)。最後catch(Exception e)的這個catch block有一個術語,叫做blanket catch,用來捕抓除了Error型態以外的全部例外。這種寫法是因為有時候鄉民們不希望自己的method丟出例外,因此用一個blanket catch把所有例外都捕捉起來。由於Error例外在Java語言中代表嚴重的錯誤,通常是由JVM所發出,例如OutOfMemoryError,而且一旦發生大部分的情況會導致程式終止。因此blanket catch通常只捕捉Exception而非Throwable。但如果鄉民們在某種特殊情況下想要連Error都一起捕捉,則可以用catch(Throwable e)的方式來實作blanket catch。

螢幕快照 2013-11-06 下午4.51.56


Java的例外類別繼承架構,捕捉Exception會捕捉除了Error以外的全部例外。


當多個catch block同時出現的時候,這些catch block出現的順序就很重要。如下圖程式片段所示,如果把catch(Exception e)寫在其他catch block前面,那麼所有的例外都會被第一個catch(Exception e)給捕捉到,後面那兩個catch block(9~12行)也就沒有機會被執行到。



   1: public void incorrect_try_multiple_catch(){
   2:     try{
   3:         throwIOException();
   4:         throwSQLException();
   5:     }
   6:     catch(Exception e){
   7:           // blanket catch
   8:     }
   9:     catch(IOException e){
  10:     }
  11:     catch(SQLException e){
  12:     }
  13: }


  • finally:最後這個finally block是用來釋放在try block裡面所使用的資源。不管在try block是否發生例外,只要寫了finally block,程式的執行順序最後一定會跑到這裡面。就算是直接在try或是catch裡面使用return指令,finally block也還是會被執行。請看下列程式範例:


   1: public static int try_finally_with_return() {
   2:         try {
   3:             System.out.println("execute try block");
   4:             return 1;
   5:         }
   6:         finally{
   7:             System.out.println("execute finally block");
   8:             return 0;
   9:         }
  10: }
  11:  
  12: public static void main( String[] args )
  13: {
  14:     System.out.println("call try_finally_with_return : " 
  15:                             + try_finally_with_return());
  16: }

 

鄉民們猜一下main()程式呼叫try_finally_with_return()之後會傳回1還是0?答案是傳回0,因為finally block一定會被執行。


execute try block
execute finally block
call try_finally_with_return : 0

世事無絕對,當然也有例外。當JVM執行到try block或是catch block裡面的程式碼,但是JVM自己本身卻被終止執行時,finally block便不會被執行到。請參考以下範例:



   1: public static void main( String[] args )
   2: {
   3:     try {
   4:         System.out.println("execute try block");
   5:         System.exit(0);
   6:     } 
   7:     finally{
   8:         System.out.println("execute finally block");
   9:     }
  10: }

 

因為在try block裡面直接呼叫System.exit(0),終止整個程式的執行,所以finally block並不會被執行到。執行結果如下列所示:


   execute try block

***


友藏內心獨白:明日待續。

沒有留言:

張貼留言