try、catch、throw、throws、finally詳解
一.關鍵字:throw,throws,try和catch的用法如下:
1、throws出現在方法的宣告中,表示該方法可能會丟擲的異常,允許throws後面跟著多個異常型別
2、throw出現在方法體中,用於丟擲異常。當方法在執行過程中遇到異常情況時,將異常資訊封裝為異常物件,然後throw,告知使用者。
3、try出現在方法體中,它自身是一個程式碼塊,表示嘗試執行程式碼塊的語句。如果在執行過程中有某條語句丟擲異常,那麼程式碼塊後面的語句將不被執行。
4、catch出現在try程式碼塊的後面,自身也是一個程式碼塊,用於捕獲異常try程式碼塊中可能丟擲的異常。catch關鍵字後面緊接著它能捕獲的異常型別,所有異常型別的子類異常也能被捕獲。
二.為什麼要使用 finally
1.假設 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;
2.但是當 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; //釋放資源 }
3.這樣,就需要在每一個可能返回的地方,以及每一個可能出現異常而導致程式跳轉的地方,考慮如何釋放資源,導致複雜和冗餘。
所以,需要finally語句。
把資源釋放或狀態還原的程式碼放到finally塊中,可以保證在try和catch語句執行完後,一定會執行finally語句塊,而不用考慮各種複雜的跳轉情況。
int count = 0;
try{
count++;
if(count == 1)throw new Exception();
}catch(Exception e){
}finally{
count = 0;
}
4.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"; 若開啟,則替換"after return"
}
}
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語句有返回值,則此返回值將替換掉臨時區域的返回值
5.驗證finally真正執行順序
package test;
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塊都一定會執行!!