java try、catch、finally及finally執行順序詳解

轉載自(原文地址)

1.爲什麼要用finally


先看一個沒有finally的異常處理try-catch語句:
假設count爲要使用到的資源,並且用完要求釋放此資源。那麼我們可以把釋放資源的語句放到try-catch後執行,當前的程序不管是在執行完try語句塊還是catch語句塊,都會順序執行到下面釋放資源的語句。
int count = 0;  //初始化資源
try{
  count++;
  if(count == 1) throw new Exception("Exception in try");
}catch(Exception e){
  System.out.println("catch block");
}
count = 0; //釋放資源
但是,如果在try或catch中有多條return語句,那麼在每條return語句之前,都要先執行釋放資源的語句:
public void f() throws Exception {
 int count = 0;  //初始化資源
 try{
   doSomething;
   statementMayCauseException;  //可能會拋出異常的語句,若異常沒有被catch,則直接拋出,也不會執行到try-catch下面的語句
   doSomething;
   if(count == 1) throw new Exception1("E1 in try");
   if(count == 2) throw new Exception2("E2 in try");
 }catch(Exception1 e){
   count = 0; //釋放資源
   throw e;  //再次把異常拋出,讓上一級捕獲。此時將不會執行catch外的語句,所以要先釋放資源
 }catch(Exception2 e){
  count = 0; //釋放資源
  return; //返回了,也不會執行catch外的語句,所以要先釋放資源
 }
 count = 0; //釋放資源
}
這樣,就需要在每一個可能返回的地方,以及每一個可能出現異常而導致程序跳轉的地方,考慮如何釋放資源,導致複雜和冗餘。
所以,需要finally語句。
把資源釋放或狀態還原的代碼放到finally塊中,可以保證在try和catch語句執行完後,一定會執行finally語句塊,而不用考慮各種複雜的跳轉情況。
int count = 0;
try{
 count++;
 if(count == 1)throw new Exception();
}catch(Exception e){
}finally{
 count = 0;
}
2.finally什麼時候執行
finally在return語句之後,跳轉到上一級程序之前執行。
public class Test { 
 public static void main(String[] args) {  
  System.out .println(test ());  
 }   
 public static String test() {  
  try {  
   System.out .println("try block");  
   return test1 ();  
  } finally {  
   System.out .println("finally block");
   //return "finally";    
  }  
 }  
 public static String test1() {  
  System.out .println("return statement");  
  return "after return";  
 }  
}
結果:
try block
return statement
finally block
after return
分析:
1.try語句塊,return test1(),則調用test1方法
2.test1()執行後返回"after return",返回值"after return"保存在一個臨時區域裏
3.執行finally語句塊。若finally語句有返回值,則此返回值將替換掉臨時區域的返回值
4.將臨時區域的返回值送到上一級方法中。


 
親測是正確的:如果若finally語句有返回值,則此返回值將替換掉臨時區域的返回值
參考:
《thinking in Java》
 
http://blog.csdn.net/mymyway/article/details/7954549


 
2,驗證finally真正執行順序
 
package lee;
    import java.io.*;
    public class Test1{
    public static void main(String argv[]){
      Test1 m=new Test1();
    System.out.println(m.amethod());
    }
    public int amethod(){
       try{
           FileInputStream dis =new FileInputStream("Hello.txt"); //1,拋出異常
       }catch ( Exception ex) {
               System.out.println("No such file found");   //2.catch捕獲異常,並執行
               return -1;                                  //4,return 返回
       }finally{
               System.out.println("Doing finally");  //3.finally一定會執行,在return之前。(準確說,應該是return ;語句)
       }
        return 0;
    }
    }
    輸出結果爲:
    No such file found
    Doing finally
    -1


 
總結:finally其實是僅在return ; 語句執行前執行,如果return 一個函數,那麼會先執行函數,但如果函數內有(return ;)語句,那麼finally就會在這個(return ;)語句前執行。
ps:如果catch塊有異常向外拋出,執行順序呢:我執行說,你拋你得異常,我finally我的語句,我倆互不干涉,你別管我啥時執行,但我一定會執行的親。 = =
 
關於finally,此時,應該很明朗了  您只需記着一點:除非調用system.exit()讓程序退出或斷電等因素致使程序中止,否則,無論任何因素,finally塊都一定會執行!!

發佈了10 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章