您好,登錄后才能下訂單哦!
示例1:
public static String hello() { String s = "商務"; try { return s; } catch (Exception e) { return "catch進來了"; } finally { s = "你好世界"; return s; } }
返回結果:你好世界,此時的返回順序是 finally > try
示例2:
public static String hello() { String s = "商務"; try { return s; } catch (Exception e) { return "catch進來了"; } finally { s = "你好世界"; } }
返回結果:商務
因為在 try 處會進行 s 值的緩存
示例3:
public static void hehe() { int a = 10; try { a += 1; System.out.println(a); throw new Exception("catch測試"); } catch (Exception e) { e.printStackTrace(); a += 10; System.out.println(a); } finally { a += 10000; System.out.println(a); } System.out.println(a); }
返回結果:
11
21
10021
10021
故意在 try 處拋出一個異常進入 catch,此時返回的順序是 try > catch > finally > 最后一行代碼
補充知識:Java異常獲取中try-catch-finally塊執行順序
最近看面試題,發現這個比較好玩,try-catch-finally塊的執行順序問題。
一般認為,finally最后執行,做收尾工作,無論try塊是否捕獲異常,最后finally都會工作。但是這樣還是比較籠統,如果沒有catch,而是將異常拋出,讓其他方法處理,那么是先進入其他方法還是先執行finally?如果try塊中return了,那么finally還執行不執行?進一步,如果try、finally全部有return,那么執行是怎樣的過程?
確實,異常這些還是最早學Java的時候學的,當時似乎也沒考慮這么多。借此機會研究一下異常獲取的順序。
節省時間,直接結論:
try->catch->finally按順序執行,不管是否有異常,不管try中有什么操作,就算是return,也得往后稍稍,最后這個方法一定是要執行finally。
如果try中拋出異常,而異常是留給上層方法處理,那么在拋出后,仍然運行finally,然后再回溯到上層。
自然,如果try中有return——也算是回溯了,返回值會存在棧中等待,等finally運行之后再回溯。
而如果finally中有return,那么直接從finally中結束方法。
如果在方法中直接結束程序,即調用System.exit()方法,那么就直接結束了,此時finally是不執行的。由此可以認為,特殊情況導致程序的退出是可能導致一些問題的。畢竟finally一般寫的是關閉對象、資源的代碼。
通過代碼分析:
先寫了一個包含情況比較多的例子:
package me.iwts; public class Main{ public static int rank; public static void solve1() throws Exception{ try { System.out.println("solve 1 try,rank: "+rank++); throw new Exception("throw by solve 1"); }finally { System.out.println("solve 1 finally,rank: "+rank++); } } public static void solve2(){ try{ System.out.println("solve 2 try,rank: "+rank++); solve1(); }catch (Exception ex){ System.out.println("catch exception : "+ex.getMessage()+",rank: "+rank++); }finally { System.out.println("solve 1 finally,rank: "+rank++); } } public static void main(String args[]) { rank = 1; solve2(); System.out.println("over"); } }
rank是計數。可以看到,整體上是先調用solve2方法,在其中調用solve1,solve1拋出了一個異常,讓solve2捕獲處理。大家可以先自己猜一下。
下面是返回答案:
solve 2 try,rank: 1
solve 1 try,rank: 2
solve 1 finally,rank: 3
catch exception : throw by solve 1,rank: 4
solve 1 finally,rank: 5
over
根據上面的結果可以分析:try-catch-finally執行順序:首先是try執行,如果發生異常,那么直接捕獲異常,最后執行finally。但是,如果拋出異常,例如在solve1方法中,throw了一個異常,那么不會立刻回溯到上一個方法,而是仍然執行finally。
通過solve1的執行,我們可以認為,finally之前的所有代碼,正常執行,但是返回之類的,全部被“卡”了下來,只有在finally執行之后,才能繼續執行。
這里就又有疑惑了,一般認為throw了一個異常,就算是回溯了,為什么finally仍然執行了?如果這個不夠明顯,那么再看這個代碼:
package me.iwts; public class Main{ public static int solve(){ try{ System.out.println("try"); return 1; }finally { System.out.println("finally"); return 2; } } public static void main(String args[]) { System.out.println(solve()); } }
返回值是多少?
try
finally
2
try塊都已經return了,最后為什么是返回的return2?并且try塊確實是運行了。再改一下代碼:
package me.iwts; public class Main{ public static int solve(){ int i = 1; try{ System.out.println("try"); return i++; }finally { System.out.println("finally"); return i; } } public static void main(String args[]) { System.out.println(solve()); } }
注意,try塊返回了i++,那么我們debug就能看出來return這句到底是執行還是沒執行,那么有這樣的圖:
可以看到,return確實是執行的。
所以,認為finally是無論怎樣一定在方法的最后結束前執行的。搜了一些資料,是說finally會在方法結束之前執行,而之前所有的執行,包括return,全部都停留在棧中,而finally最終執行后才繼續。所以這樣也能解釋,第一次代碼本應該回溯的代碼執行完finally后才回溯,return的時候也是等finally執行之后再執行。
或許“return的時候也是等finally執行之后再執行”這句話又引出了一個問題:finally究竟是直接運行完結束,還是運行完之后再回到原來return的地方?
這里我們可以把i++換成++i,結果就不截圖了——finally就是最終執行,如果有return,直接從finally返回。
還有一種情況,直接結束程序會怎么樣?
package me.iwts; public class Main{ public static void solve(){ try{ System.out.println("try"); System.exit(0); }finally { System.out.println("finally"); } } public static void main(String args[]) { solve(); } }
結果:
try
強制結束大過天。由此,也可以認為特殊情況導致程序直接結束,不會執行finally。因為finally一般寫的都是關閉對象、資源的代碼,所以這些特殊情況導致的程序強制結束,可能會引發一些問題的。
以上這篇Java.try catch finally 的執行順序說明就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。