JAVA學習筆記(異常處理)

關於finally塊的運行順序,在學習階段不是很明確。查詢了一些資料後,大概可以得出以下結論:“finally塊是在下級函數向上級調用的函數跳轉前(無論是通過return還是throw exception的方式回到調用函數)執行”,具體參照以下兩個示例。

    public static void main(String[] args) {
        test t=new test();
        System.out.println(t.f());
    }   
    public String f() {
        try{
            System.out.println("try block");
            return f2();
        }
        finally{
            System.out.println("finally block");
            return "finally";
        }
    }
    public String f2(){
        System.out.println("returning");
        return "return";
    }

此時的輸出結果爲

try block
returning
finally block
finally

分析:try塊執行,運行到f()中的return**這行,按慣例先執行return語句後半部分(用於計算return的返回值),輸出returning之後,開始正式執行return語句*,將返回值*return存在一個臨時區域裏,並在程序正式由f()跳轉回main()之前,執行finally塊的語句。若finally塊內有返回值,則將此返回值替換原來臨時變量區內的返回值。因此最後輸出的不是return而是finally。

類似的:

public static void main(String[] args) {
        test t=new test();
        try{
            System.out.println(t.f());
        }
        catch(Exception e){}
    }

    public String f() {
        try{
            System.out.println("try block");
            int a=5/0;
        }
        catch(Exception e){
            System.out.println("exception block");
            throw e;
            //return "exception"
        }
        finally{
            System.out.println("finally block");
            return "finally";
        }

輸出結果仍爲:

try block
exception block
finally block
finally

此時由catch塊捕獲並拋出異常,但finally塊仍把“finally”作爲返回值返回給了main函數,並由main函數打印出來。用註釋掉的return部分替換原有的catch模塊,結果也是一樣的。

但是在finally塊中修改返回值對應的變量(而不調用return語句),實際的返回值不會被修改。

public static void main(String[] args) {
        test t=new test();
        try{
            System.out.println(t.f());
        }
        catch(Exception e){}
    }

    public String f() {
        String s;
        try{
            System.out.println("try block");
            return s="return";
        }
        finally{
            System.out.println("finally block");
            s="finally";
        }
    }

輸出爲

try block
finally block
return

可見最後被返回的變量s沒有被修改成finally。這裏要說道JAVA的值傳遞特性。JAVA沒有真正意義上(像C++)一樣的引用傳遞。而由於string類型的不可變性,對s的修改都會採用新建一個字符串並將s引用(指針)修改到新建字符串上。然而,try塊中調用的return已經反回了s的值(存在臨時區域內),即return字符串對應的地址,此時將s的值修改了也沒有實際作用。

考慮JAVA的值傳遞特性,我們可以推測,對於int之類的基礎類型的返回值,在finally塊修改而不return返回值變量,對函數返回值沒有影響(因爲return已經將變量內存儲的值存入臨時區域內)。但是對於class類型的變量返回值,如果在finally塊內修改類的成員變量等,真正的返回值中的成員變量也會對應被修改。

發佈了39 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章