今天就跟大家聊聊有關try、finally與return語句在Java中哪個先執行,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
創新互聯公司服務項目包括淶源網站建設、淶源網站制作、淶源網頁制作以及淶源網絡營銷策劃等。多年來,我們專注于互聯網行業,利用自身積累的技術優勢、行業經驗、深度合作伙伴關系等,向廣大中小型企業、政府機構等提供互聯網行業的解決方案,淶源網站推廣取得了明顯的社會效益與經濟效益。目前,我們服務的客戶以成都為中心已經輻射到淶源省份的部分城市,未來相信會繼續擴大服務區域并繼續獲得客戶的支持與信任!
Demo1
public class Test { public static void main(String[] args) { System.out.println("return value of test(): " + test()); } public static int test() { int i = 1; // if (i == 1) { // return 0; // } System.out.println("the previous statement of try block"); i = i / 0; try { System.out.println("try block"); return i; } finally { System.out.println("finally block"); } } }
Demo1的執行結果如下:
the previous statement of try block Exception in thread "main" java.lang.ArithmeticException: / by zero at com.becoda.bkms.bus.basics.web.Test2.test(Test2.java:15) at com.becoda.bkms.bus.basics.web.Test2.main(Test2.java:5)
另外,如果去掉上例中的注釋,執行結果則是:
return value of test(): 0
以上兩種情況,finally語句塊都沒有執行,說明什么問題?只有與finally相對應的try語句塊得到執行的情況下,finally語句塊才會執行,而上面都是在try語句塊之前返回(return)或者拋出異常,所以try對應的finally語句塊沒有執行。那么,即使與finally相對應的try語句塊得到執行的情況下,finally語句塊一定會執行嗎?但下面例子
Demo2
public class Test { public static void main(String[] args) { System.out.println("return value of test(): " + test()); } public static int test() { int i = 1; try { System.out.println("try block"); System.exit(0); return i; } finally { System.out.println("finally block"); } } }
Demo2的執行結果如下:
try block
finally語句塊還是沒有執行,為什么呢?因為我們在try語句塊中執行了System.exit(0)語句,終止了Java虛擬機的運行,雖然一般情況下我們不會這么干。還有情況是當一個線程在執行try語句塊或者catch語句塊時被打斷(interrupted)或者被終止(killed),與其對應的finally語句塊可能不會執行。還有更極端的情況,就是在線程運行 try 語句塊或者 catch 語句塊時,突然死機或者斷電,finally 語句塊肯定不會執行了。
finally 語句示例說明
下面看一個簡單的例子
Demo3
public class Test { public static void main(String[] args) { try { System.out.println("try block"); return; } finally { System.out.println("finally block"); } } }
Demo3的執行結果為:
try block finally block
Demo3說明 finally 語句塊在 try 語句塊中的 return 語句之前執行。我們再來看另一個例子。
Demo4
public class Test { public static void main(String[] args) { System.out.println("reture value of test() : " + test()); } public static int test() { int i = 1; try { System.out.println("try block"); i = 1 / 0; return 1; } catch (Exception e) { System.out.println("exception block"); return 2; } finally { System.out.println("finally block"); } } }
Demo4的執行結果為:
try block exception block finally block reture value of test() : 2
Demo4說明了 finally 語句塊在 catch 語句塊中的 return 語句之前執行。
從上面的Demo3和Demo4,我們可以看出,其實finally語句塊時在try或者catch中的return語句之前執行的,更加一般的說法是,finally語句塊應該是在控制轉移語句之前執行,控制轉移語句除了return外,還有break和continue。
再來看下面兩個例子
Demo5
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { try { return 0; } finally { return 1; } } }
Demo5的執行結果為:
return value of getValue(): 1
Demo6
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { int i = 1; try { return i; } finally { i++; } } }
Demo6的執行結果為:
return value of getValue(): 1
利用我們上面分析得出的結論:finally 語句塊是在 try 或者 catch 中的 return 語句之前執行的。 由此,可以輕松的理解Demo5 的執行結果是 1。因為 finally 中的 return 1;語句要在 try 中的 return 0;語句之前執行,那么 finally 中的 return 1;語句執行后,把程序的控制權轉交給了它的調用者 main()函數,并且返回值為 1。那為什么Demo6 的返回值不是 2,而是 1 呢?按照Demo5 的分析邏輯,finally 中的 i++;語句應該在 try 中的 return i;之前執行???i 的初始值為 1,那么執行 i++;之后為 2,再執行 return i;那不就應該是 2 嗎?怎么變成 1 了呢?
說明這個問題需要了解Java虛擬機是如何編譯finally語句塊的。
Java方法是在棧幀中執行,棧幀是線程私有棧的單位,執行方法的線程會為每一個方法分配一小塊空間來作為該方法執行時的內存空間,棧幀分為三個區域:
1、操作數棧,用來保存正在執行的表達式中的操作數
2、局部變量區,用來保存方法中使用的變量,包括方法參數,方法內部聲明的變量,以及方法中使用到的對象的成員變量或類的成員變量(靜態變量),最后兩種變量會復制到局部變量區,因此在多線程環境下,這種變量需要根據需要聲明為volatile類型
3、字節碼指令區
例如下面這段代碼
try{ return expression; }finally{ do some work; }
首先我們知道,finally語句是一定會執行,但他們的執行順序是怎么樣的呢?他們的執行順序如下:
1、執行:expression,計算該表達式,結果保存在操作數棧頂;
2、執行:操作數棧頂值(expression的結果)復制到局部變量區作為返回值;
3、執行:finally語句塊中的代碼;
4、執行:將第2步復制到局部變量區的返回值又復制回操作數棧頂;
5、執行:return指令,返回操作數棧頂的值;
我們可以看到,在第一步執行完畢后,整個方法的返回值就已經確定了,由于還要執行finally代碼塊,因此程序會將返回值暫存在局部變量區,騰出操作數棧用來執行finally語句塊中代碼,等finally執行完畢,再將暫存的返回值又復制回操作數棧頂。所以無論finally語句塊中執行了什么操作,都無法影響返回值,所以試圖在finally語句塊中修改返回值是徒勞的。因此,finally語句塊設計出來的目的只是為了讓方法執行一些重要的收尾工作,而不是用來計算返回值的。
這樣就能解釋Demo6的問題了
讓我們再來看以下 3 個例子。
Demo7
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } @SuppressWarnings("finally") public static int getValue() { int i = 1; try { i = 4; } finally { i++; return i; } } }
Demo7的執行結果為:
return value of getValue(): 5
Demo8
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { int i = 1; try { i = 4; } finally { i++; } return i; } }
Demo8的執行結果為:
return value of getValue(): 5
Demo9
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"); } } public static String test1() { System.out.println("return statement"); return "after return"; } }
Demo9的執行結果為:
try block return statement finally block after return
總結:
1、finally 語句塊不一定會被執行
2、finally 語句塊在 try 語句塊中的 return 語句之前執行
3、finally 語句塊在 catch 語句塊中的 return 語句之前執行
4、finally 語句塊中的 return 語句會覆蓋 try 塊中的 return 返回
5、試圖在 finally 語句塊中修改返回值不一定會被改變
看完上述內容,你們對try、finally與return語句在Java中哪個先執行有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注創新互聯行業資訊頻道,感謝大家的支持。
網站題目:try、finally與return語句在Java中哪個先執行
標題網址:http://vcdvsql.cn/article24/gjicce.html
成都網站建設公司_創新互聯,為您提供品牌網站建設、商城網站、定制開發、網站改版、定制網站、網站維護
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯