1. 程式人生 > >Java基礎知識--try-catch-finally

Java基礎知識--try-catch-finally

看了一位博友的一片文章,講解的是關於java中關於try、catch、finally中一些問題 下面看一個例子(例1),來講解java裡面中try、catch、finally的處理流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 publicclassTryCatchFinally { @SuppressWarnings("finally") publicstaticfinalString test() { String t = ""; try{ t = "try"; returnt; catch(Exception e) { // result = "catch"; t = "catch"; returnt;
finally{ t = "finally"; } } publicstaticvoidmain(String[] args) { System.out.print(TryCatchFinally.test()); } }
  首先程式執行try語句塊,把變數t賦值為try,由於沒有發現異常,接下來執行finally語句塊,把變數t賦值為finally,然後return t,則t的值是finally,最後t的值就是finally,程式結果應該顯示finally,但是實際結果為try。為什麼會這樣,我們不妨先看看這段程式碼編譯出來的class對應的位元組碼,看虛擬機器內部是如何執行的。 我們用javap -verbose TryCatchFinally 來顯示目標檔案(.class檔案)位元組碼資訊 系統執行環境:mac os lion系統 64bit jdk資訊:Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-11M3527) Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02-402, mixed mode) 編譯出來的位元組碼部分資訊,我們只看test方法,其他的先忽略掉
public static final java.lang.String test();   Code:    Stack=1, Locals=4, Args_size=0    0:    ldc    #16; //String    2:    astore_0 3:    ldc    #18; //String try    5:    astore_0 6:    aload_0 7:    astore_3 8:    ldc    #20; //String finally    10:    astore_0 11:    aload_3 12:    areturn 13:    astore_1
14:    ldc    #22; //String catch    16:    astore_0 17:    aload_0 18:    astore_3 19:    ldc    #20; //String finally    21:    astore_0 22:    aload_3 23:    areturn 24:    astore_2 25:    ldc    #20; //String finally    27:    astore_0 28:    aload_2 29:    athrow   Exception table:    from   to  target type 3     8    13   Class java/lang/Exception 3     8    24   any 13    19    24   any LineNumberTable:    line 5: 0    line 8: 3    line 9: 6    line 15: 8    line 9: 11    line 10: 13    line 12: 14    line 13: 17    line 15: 19    line 13: 22    line 14: 24    line 15: 25    line 16: 28   LocalVariableTable:    Start  Length  Slot  Name   Signature 3      27      0    t       Ljava/lang/String;    14      10      1    e       Ljava/lang/Exception;   StackMapTable: number_of_entries = 2    frame_type = 255 /* full_frame */      offset_delta = 13      locals = [ class java/lang/String ]      stack = [ class java/lang/Exception ]    frame_type = 74 /* same_locals_1_stack_item */      stack = [ class java/lang/Throwable ] 首先看LocalVariableTable資訊,這裡面定義了兩個變數 一個是t String型別,一個是e Exception 型別 接下來看Code部分 第[0-2]行,給第0個變數賦值“”,也就是String t=""; 第[3-6]行,也就是執行try語句塊 賦值語句 ,也就是 t = "try"; 第7行,重點是第7行,把第s對應的值"try"付給第三個變數,但是這裡面第三個變數並沒有定義,這個比較奇怪 第[8-10] 行,對第0個變數進行賦值操作,也就是t="finally" 第[11-12]行,把第三個變數對應的值返回 通過位元組碼,我們發現,在try語句的return塊中,return 返回的引用變數(t 是引用型別)並不是try語句外定義的引用變數t,而是系統重新定義了一個區域性引用t’,這個引用指向了引用t對應的值,也就是try ,即使在finally語句中把引用t指向了值finally,因為return的返回引用已經不是t ,所以引用t的對應的值和try語句中的返回值無關了。 下面在看一個例子:(例2) 1 public class TryCatchFinally { 2 3     @SuppressWarnings("finally") 4     public static final String test() { 5         String t = ""; 6 7         try { 8             t = "try"; 9             return t; 10         } catch (Exception e) { 11             // result = "catch"; 12             t = "catch"; 13             return t; 14         } finally { 15             t = "finally"; 16             return t; 17         } 18     } 19 20     public static void main(String[] args) { 21         System.out.print(TryCatchFinally.test()); 22     } 23 24 } 這裡稍微修改了 第一段程式碼,只是在finally語句塊裡面加入了 一個 return t 的表示式。 按照第一段程式碼的解釋,先進行try{}語句,然後在return之前把當前的t的值try儲存到一個變數t',然後執行finally語句塊,修改了變數t的值,在返回變數t。 這裡面有兩個return語句,但是程式到底返回的是try 還是 finally。接下來我們還是看位元組碼資訊 public static final java.lang.String test();   Code:    Stack=1, Locals=2, Args_size=0    0:    ldc    #16; //String    2:    astore_0 3:    ldc    #18; //String try    5:    astore_0 6:    goto    17    9:    astore_1 10:    ldc    #20; //String catch    12:    astore_0 13:    goto    17    16:    pop    17:    ldc    #22; //String finally    19:    astore_0 20:    aload_0 21:    areturn   Exception table:    from   to  target type 3     9     9   Class java/lang/Exception 3    16    16   any LineNumberTable:    line 5: 0    line 8: 3    line 9: 6    line 10: 9    line 12: 10    line 13: 13    line 14: 16    line 15: 17    line 16: 20   LocalVariableTable:    Start  Length  Slot  Name   Signature 3      19      0    t       Ljava/lang/String;    10      6      1    e       Ljava/lang/Exception;   StackMapTable: number_of_entries = 3    frame_type = 255 /* full_frame */      offset_delta = 9      locals = [ class java/lang/String ]      stack = [ class java/lang/Exception ]    frame_type = 70 /* same_locals_1_stack_item */      stack = [ class java/lang/Throwable ]    frame_type = 0 /* same */ 這段程式碼翻譯出來的位元組碼和第一段程式碼完全不同,還是繼續看code屬性 第[0-2]行、[3-5]行第一段程式碼邏輯類似,就是初始化t,把try中的t進行賦值try 第6行,這裡面跳轉到第17行,[17-19]就是執行finally裡面的賦值語句,把變數t賦值為finally,然後返回t對應的值 我們發現try語句中的return語句給忽略。可能jvm認為一個方法裡面有兩個return語句並沒有太大的意義,所以try中的return語句給忽略了,直接起作用的是finally中的return語句,所以這次返回的是finally。 接下來在看看複雜一點的例子:(例3) public class TryCatchFinally {     @SuppressWarnings("finally") public static final String test() {         String t = ""; try {             t = "try";             Integer.parseInt(null); return t;         } catch (Exception e) {             t = "catch"; return t;         } finally {             t = "finally"; // System.out.println(t); // return t;         }     } public static void main(String[] args) {         System.out.print(TryCatchFinally.test());     } } 這裡面try語句裡面會丟擲 java.lang.NumberFormatException,所以程式會先執行catch語句中的邏輯,t賦值為catch,在執行return之前,會把返回值儲存到一個臨時變數裡面t ',執行finally的邏輯,t賦值為finally,但是返回值和t',所以變數t的值和返回值已經沒有關係了,返回的是catch 例4: public class TryCatchFinally {     @SuppressWarnings("finally") public static final String test() {         String t = ""; try {             t = "try";             Integer.parseInt(null); return t;         } catch (Exception e) {             t = "catch"; return t;         } finally {             t = "finally"; return t;         }     } public static void main(String[] args) {         System.out.print(TryCatchFinally.test());     } } 這個和例2有點類似,由於try語句裡面丟擲異常,程式轉入catch語句塊,catch語句在執行return語句之前執行finally,而finally語句有return,則直接執行finally的語句值,返回finally 例5: public class TryCatchFinally {     @SuppressWarnings("finally") public static final String test() {         String t = ""; try {             t = "try";             Integer.parseInt(null); return t;         } catch (Exception e) {             t = "catch";             Integer.parseInt(null); return t;         } finally {             t = "finally"; //return t;         }     } public static void main(String[] args) {         System.out.print(TryCatchFinally.test());     } } 這個例子在catch語句塊添加了Integer.parser(null)語句,強制丟擲了一個異常。然後finally語句塊裡面沒有return語句。繼續分析一下,由於try語句丟擲異常,程式進入catch語句塊,catch語句塊又丟擲一個異常,說明catch語句要退出,則執行finally語句塊,對t進行賦值。然後catch語句塊裡面丟擲異常。結果是丟擲java.lang.NumberFormatException異常 例子6: public class TryCatchFinally {     @SuppressWarnings("finally") public static final String test() {         String t = ""; try {             t = "try"

相關推薦

Java基礎知識--try-catch-finally

看了一位博友的一片文章,講解的是關於java中關於try、catch、finally中一些問題 下面看一個例子(例1),來講解java裡面中try、catch、finally的處理流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1

Java異常機制--try catch finally 執行順序詳解

引言 關於try catch finally 執行順序的筆試面試題目非常的多,我曾經在牛客網刷題的時候不止一次的碰到過,而且不止一次的做錯過,這裡面需要涉及的細節如果不弄清楚每次做題就會產生似是而非的感覺。這次查閱了很多相關資料,關於try catch fin

Java異常處理try-catch-finally的執行過程

try-catch-finally程式塊的執行流程以及執行結果比較複雜。基本執行過程如下: 程式首先執行可能發生異常的try語句塊。如果try語句沒有出現異常則執行完後跳至finally語句塊執行;如果try語句出現異常,則中斷執行並根據發生的異常型別跳至相應的catch語

Java解惑之try catch finally

此文起因是由於論壇中出現的這兩個討論貼: 至於這個問題是否值得深究我們不做討論,人跟人觀點不一樣,我就覺得很有意思,所以可以試著分析一下。 不過要提前說明一下,可能有的地方我的理解並不正確或者措辭並不恰當,還希望高手指正。 首先,還是先看下問題,程式碼如下: Java程式碼   priva

關於java中的try-catch-finally語句和return

本部落格所有轉載文章的所有權都歸原作者所有,這裡只是共享以及傳播知識作用,每篇文章都會在開頭標明出處,請尊重原作者版權。 第一:return語句並不是函式的最終出口,如果有finally語句,這在return之後還會執行finally(return的值會暫存在棧裡面,

Java小細節——try/catch/finally/return不得不說的祕密

閱讀2分鐘,掌握一個Java小細節,你值得擁有! java面試經常能看到這道題目: try {} 裡有一個return語句,那麼緊跟在這個try後的finally {}裡的程式碼會不會被執行?什麼時候被執行?在return前還是後? t

java中使用try-catch-finally一點值得注意的事

我們知道,try負責圈定可能會出異常的程式碼;catch負責處理try中可能異常的處理,如記錄錯誤日誌,使業務能夠正常執行;finally負責資源釋放等善後工作,無論有無異常都必須要執行的程式碼,一般

java 異常捕捉 ( try catch finally ) 你真的掌握了嗎?

前言:java 中的異常處理機制你真的理解了嗎?掌握了嗎?catch 體裡遇到 return 是怎麼處理? finally 體遇到 return 怎麼辦?finally 體裡有 System.exit() 方法怎麼處理?當 catch 和 finally 體裡同時遇上 r

關於java 異常捕捉 ( try catch finally ) 執行流程

java中使用try catch finally做異常處理的情形較為常見,關於執行具體不同情況下的執行流程,在另一篇帖子中看到,說明較為詳細,但例子沒看太懂,故用自己的程式碼做貼留念。 參考部落格 以下內容在‘假設方法需要返回值’的前提下,如沒有此前提

Java基礎(一)異常處理關鍵字:try catch finally throw throws

cut main 5.1 模型 指針 str control 情況 實例   嗨咯,大家晚上好,我的博客首篇開始了 ,我們一起加油吧! 都說java 語言是非常健壯性 如:垃圾回收機制、內存模型、異常處理,強類型轉換、跨平臺,等等,使得Java語言的受到青睞。今天我們先來聊

Android面試之java基礎try-catch-finally-return的執行先後順序問題

還是一個被個程式猿們討論多時的問題,也是眾軟體公司面試題中很鍾情的一個問題,更是一個考查程式猿對Java基礎知識掌握理解程度的問題,就是本文要說的try-catch-finally-return的執行先後順序問題 先說明幾個原則 。 1、不論是否能捕捉到異常,fin

Java異常捕獲之一道try-catch-finally語句題

span pri div system 處理機 out nal exception for 今天,學習了try-catch-finally語句,本來覺得蠻簡單、易懂的。搜了一道相關類型的題。結果信心被潑了盆冷水。先把題Mark一下,出去透透風。 1 public cla

java try-catch-finally輸出異常

java try-catch-finally輸出異常

深入剖析javatrycatchfinally語句

ppr ive after 內容 我們 title oid stat blog 一、前言 前些天參加面試的時候有一道題: public class test { public static void main(String[] args){

Javatry--catch-- finally、throw、throws 的用法

一、try {..} catch {..}finally {..}用法 try {   執行的程式碼,其中可能有異常。一旦發現異常,則立即跳到catch執行。否則不會執行catch裡面的內容 } catch (Exception e) {  除非try裡面執行程式碼發生了異常,否則這裡的程式碼不會執行 }

java 異常處理機制,throws與throw,try-catch-finally

java 異常處理機制 1.Java異常處理 2.try-catch-finally的程式流程圖 3.關鍵解讀 4.demo 5.不捕獲異常時的情況 在編寫程式時,經常要在可能出現錯誤的地方

java 異常處理方式之一 trycatch——finally

java 異常處理方式之一: try—catch——finally 1. 如何處理Exception的異常 2. 注: 3.dome 1. 如何處理Exception的異常 Java提供的是異常處理的抓拋模型為

Javatry catch finally 中有異常和return時處理先後

public class TestDemo { private static String output = ""; public static void foo(int i) { try { if (i == 1) { throw new Exception(); }

java之集合總結,異常(try...catch...finally,丟擲throws)

一. 集合總結 1. 單列集合 (Collection) 1.1 執行緒不安全的 jdk1.2 ArrayList 查詢快 增刪慢(相對) LinkedList 查詢慢 增刪快(相對) HashSet 去重 TreeS

JAVA try catch finally return 執行順序

JAVA try catch finally return 執行順序 參考:https://www.cnblogs.com/superFish2016/p/6687549.html 一、結論 1、不管有沒有出現異常,finally塊中程式碼都會執行; 2、當try和catch中有