當finall塊中包含return語句時,Eclipse會給出警告「finally block does not complete normally」,緣由分析以下:java
一、無論try塊、catch塊中是否有return語句,finally塊都會執行。
二、finally塊中的return語句會覆蓋前面的return語句(try塊、catch塊中的return語句),因此若是finally塊中有return語句,Eclipse編譯器會報警告「finally block does not complete normally」。web
三、若是finally塊中包含了return語句,即便前面的catch塊從新拋出了異常,則調用該方法的語句也不會得到catch塊從新拋出的異常,而是會獲得finally塊的返回值,而且不會捕獲異常。函數
結論,測試
finally 內部使用 return 語句是一種很很差的習慣,若是try中還有return語句,它會覆蓋了try 區域中 return 語句的返回值,程序的可讀性差spa
面對上述狀況,其實更合理的作法是,既不在 try block 內部中使用 return 語句,也不在 finally 內部使用 return 語句,而應該在 finally 語句以後使用 return 來表示函數的結束和返回code
結論:
一、無論有木有出現異常,finally塊中代碼都會執行;
二、當try和catch中有return時,finally仍然會執行;
三、finally是在return後面的表達式運算後執行的(此時並無返回運算後的值,而是先把要返回的值保存起來,管finally中的代碼怎麼樣,返回的值都不會改變,任然是以前保存的值),因此函數返回值是在finally執行前肯定的;
四、finally中最好不要包含return,不然程序會提早退出,返回值不是try或catch中保存的返回值。
舉例:
狀況1:try{} catch(){}finally{} return;
顯然程序按順序執行。
狀況2:try{ return; }catch(){} finally{} return;
程序執行try塊中return以前(包括return語句中的表達式運算)代碼;
再執行finally塊,最後執行try中return;
finally塊以後的語句return,由於程序在try中已經return因此再也不執行。
狀況3:try{ } catch(){return;} finally{} return;
程序先執行try,若是遇到異常執行catch塊,
有異常:則執行catch中return以前(包括return語句中的表達式運算)代碼,再執行finally語句中所有代碼,
最後執行catch塊中return. finally以後也就是4處的代碼再也不執行。
無異常:執行完try再finally再return.
狀況4:try{ return; }catch(){} finally{return;}
程序執行try塊中return以前(包括return語句中的表達式運算)代碼;
再執行finally塊,由於finally塊中有return因此提早退出。
狀況5:try{} catch(){return;}finally{return;}
程序執行catch塊中return以前(包括return語句中的表達式運算)代碼;
再執行finally塊,由於finally塊中有return因此提早退出。
狀況6:try{ return;}catch(){return;} finally{return;}
程序執行try塊中return以前(包括return語句中的表達式運算)代碼;
有異常:執行catch塊中return以前(包括return語句中的表達式運算)代碼;
則再執行finally塊,由於finally塊中有return因此提早退出。
無異常:則再執行finally塊,由於finally塊中有return因此提早退出。
最終結論:任何執行try 或者catch中的return語句以前,都會先執行finally語句,若是finally存在的話。
若是finally中有return語句,那麼程序就return了,因此finally中的return是必定會被return的,
編譯器把finally中的return實現爲一個warning。orm
下面是個測試程序public class FinallyTest { public static void main(String[] args) { System.out.println(new FinallyTest().test());; } static int test() { int x = 1; try { x++; return x; } finally { ++x; } } }結果是2。
分析: 在try語句中,在執行return語句時,要返回的結果已經準備好了,就在此時,程序轉到finally執行了。 在轉去以前,try中先把要返回的結果存放到不一樣於x的局部變量中去,執行完finally以後,在從中取出返回結果, 所以,即便finally中對變量x進行了改變,可是不會影響返回結果。 它應該使用棧保存返回值。
public class Ex1 {
public static void main(String[] args) {
System.out.println(Ex1.getResult());
}
public static int getResult(){
int a =100;
try{
return a+10; //注意,java的基礎數據類型是值傳遞,這裏的返回值已經和上面的a沒有關係了
}catch(Exception e){ip
e.printStackTrace();
}finally{
return a; //最後再把值重定向到a(至關於將try中的返回值覆蓋掉),因此輸出仍是100
}
}
}資源
再看一個例子:get
public class Ex1 {
public static void main(String[] args) {
try{
System.out.println(Ex1.getResult());
}catch(Exception e){
e.printStackTrace();
System.out.println("截獲異常catch");
}finally{
System.out.println("異常處理finally");
}
}
public static int getResult() throws Exception{
int a =100;
try{
a=a+10;
throw new RuntimeException();
}catch(Exception e){
System.out.println("截獲異常並從新拋出異常");
throw new Exception();
}finally{
return a;
}
}
}
輸出以下:
截獲異常並從新拋出異常
110
異常處理finally
關鍵的「截獲異常catch」卻沒有執行!!!
緣由是在getResult()的finally中return一個值,等同於告訴編譯器該方法沒有異常,但實際上異常是有的,這樣的結果是該方法的調用者卻捕獲不到異常,相對於異常被無故的被吃掉了,隱藏殺機啊!!
結論:不要再finally中試圖return一個值,這樣可能會致使一些意想不到的邏輯錯誤,finally就是用來釋放資源的!!