標籤:
在只有try-catch語句中,如果catch塊中出現了return語句或者拋出了異常,那麼catch之後的語句是執行不到的;但是如果將代碼放入finally中,即使catch中出現了return語句或者拋出了異常,finally中的代碼仍然是可以執行到的。看下面的程式:
public class Test {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(test());}public static int test() {int b = 23;try {System.out.println("yes");return b += 88;} catch (Exception e) {System.out.println("error:" + e);}System.out.println("next");return b;}}
因為try塊中沒有出現異常,且有return語句,所以後面的輸出程式沒有執行。但如果把輸出程式放到finally中,則會執行到。
try {System.out.println("yes");return b += 88;} catch (Exception e) {System.out.println("error:" + e);}finally{System.out.println("finally");}
看第一段程式,最後有一個return b語句。如果缺少這條語句,程式會報錯,提示test()方法必須返回一個int類型的值。可能有人會發現try語句中已經有了一個return語句了,為何還會報錯呢。這是因為try塊中放入的是可能出現異常的代碼,如果發生了異常,系統就不會再執行try塊中未執行的代碼。所以存在一種情況就是程式還沒執行到return語句時,就因為異常去執行catch中語句。這樣的話,程式就跳過了return語句,所以必須在後面加上一個return。
另外,如果我們把return語句放到finally塊中,會有“finally does not complete normally”警告出現。原因可能如下:
1、不管try塊、catch塊中是否有return語句,finally塊都會執行。
2、finally塊中的return語句會覆蓋前面的return語句(try塊、catch塊中的return語句),所以如果finally塊中有return語句,Eclipse編譯器會警示告“finally block does not complete normally”。
3、如果finally塊中包含了return語句,即使前面的catch塊重新拋出了異常,則調用該方法的語句也不會獲得catch塊重新拋出的異常,而是會得到finally塊的傳回值,並且不會捕獲異常。
下面來看finally和return的問題。如果我們在第一段程式中的finally中添加一些代碼,如下所示:
package com.imooc1;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(test());}public static int test() {int b = 23;try {System.out.println("yes");return b += 88;} catch (Exception e) {System.out.println("error:" + e);} finally {if (b > 25) {System.out.println("b>25:" + b);}System.out.println("finally");}return b;}}
程式的運行結果會如何呢?這個主要是用來測試return和finally語句到底哪個先執行。在try語句中,返回了b=111; 在finally語句中判斷是否大於25,如果大的話就輸出大.最終結果如下:
yes
b>25:111
finally
111
這說明finally語句是在try的return語句執行之後,return返回之前執行的。
如果把finally語句改成這樣(會有上面所說的警告出現):
package com.imooc1;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(test());}public static int test() {int b = 23;try {System.out.println("yes");return b += 88;} catch (Exception e) {System.out.println("error:" + e);} finally {if (b > 25) {System.out.println("b>25:" + b);}System.out.println("finally");return 100;}//return b;}}
結果變為了:
yes
b>25:111
finally
100
這說明finally塊中的return語句會把try塊中的return覆蓋!
如果把finally中語句變成這樣:
package com.imooc1;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(test());}public static int test() {int b = 23;try {System.out.println("yes");return b += 88;} catch (Exception e) {System.out.println("error:" + e);} finally {if (b > 25) {System.out.println("b>25:" + b);}System.out.println("finally");b=100;}return b;}}
也就是在finally中改變b的值. 那麼返回結果到底是原來的b值呢, 還是更改過的b值呢?結果如下:
yes
b>25:111
finally
111
說明了一個問題,如果finally語句中沒有返回語句覆蓋的話,那麼原來的傳回值就不會變,不管你是不是改變了要返回的那個變數。但如果程式因為出現了異常而沒有執行try中的return,則這樣的改變是有效。測試代碼如下:
package com.imooc1;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(test());}public static int test() {int b = 23;int a = 0;try {System.out.println("b/a"+b/a);return b += 88;} catch (ArithmeticException e) {e.printStackTrace();} finally {if (b > 25) {System.out.println("b>25:" + b);}System.out.println("finally");b=100;}return b;}}
程式運行結果如下:
java.lang.ArithmeticException: / by zero
at com.imooc1.Test.test(Test.java:14)
at com.imooc1.Test.main(Test.java:7)
finally
100
Java中try-catch-finally的一點理解