1. 程式人生 > >Java程式碼中的try ..finally返回值問題

Java程式碼中的try ..finally返回值問題

首先明確一點,finally 塊中的 return 返回後方法結束執行,不會再執行 try 塊中的 return 語句。
那麼如果finally修改某個變數會影響try中的返回值嗎?程式碼如下:

private static Map<String, String> finallyTestByMap() {
        Map<String, String> map = new HashMap<String, String>();
        map.put("KEY", "INIT");
    try {
        map.put("KEY", "TRY");
        return map;
    } catch (Exception e) {
        map.put("KEY", "CATCH");
    } finally {
        map.put("KEY", "FINALLY");
        map = null;  //不管用
    }
    return map;
}

此map.get(“KEY”)的結果為FINALLY。

private static Integer finallyTestByInt() {
    Integer a= 1;
//        int a = 1;
        try {
            a = 2;
            return a;
        } catch (Exception e) {
            a= 3;
        } finally {
            a = 4;
        }
        return a;
    }

此a 的返回值為2。

private static String finallyTestByString() {
    String a = "init";
    try {
        a = "try";
        return a;
    } catch (Exception e) {
        a= "catch";
    } finally {
        a = "finally";
    }
    return a;
}

此 a 的返回值為try。

private static List<String> finallyTestByList() {
    List<String> a = new ArrayList<>(1);
    try {
        a.add("try");
        return a;
    } catch (Exception e) {
        a.add("catch");
    } finally {
        a.set(0, "finally");
        a= null;
    }
    return a;
}

此 a 的返回值為finally。

此前在網上查了很多,基本就分為基本型別和引用型別的區別。
如果是基本型別,finally塊的操作不會改變try塊中的;引用型別則會受影響。
現在來看下編譯後的程式碼。

private static Map<String, String> finallyTestByMap() {
        Map<String, String> map = new HashMap();
        map.put("KEY", "INIT");
    try {
        map.put("KEY", "TRY");
        HashMap var1 = map;
        return var1;
    } catch (Exception var5) {
        map.put("KEY", "CATCH");
    } finally {
        map.put("KEY", "FINALLY");
        map = null;
    }

    return map;
}

private static Integer finallyTestByInt() {
    Integer a = 1;

    try {
        a = 2;
        Integer var1 = a;
        return var1;
    } catch (Exception var5) {
        a = 3;
    } finally {
        a = 4;
    }

    return a;
}

private static String finallyTestByString() {
    String a = "init";

    try {
        a = "try";
        String var1 = a;
        return var1;
    } catch (Exception var5) {
        a = "catch";
    } finally {
        a = "finally";
    }

    return a;
}

private static List<String> finallyTestByList() {
    ArrayList a = new ArrayList(1);

    try {
        a.add("try");
        ArrayList var1 = a;
        return var1;
    } catch (Exception var5) {
        a.add("catch");
    } finally {
        a.set(0, "finally");
        a = null;
    }

    return a;
}

仔細看下try中的不同,原來jvm在try中又新建了一個副本,現在看來就明白了原因。
其實按照引用型別和基本型別區分感覺有點不妥,String也是引用型別,但表現了基本型別的結果。
其實說到底可以歸為賦值的問題,引用也是對不同地址的賦值,只要進行的是賦值操作,finally的操作就不會影響try中的副本,就像你和我指向同一個籃子,籃子中有一個蘋果,你是副本,就算我掛了籃子還在,並沒有直接操作籃子,籃子中還是一個蘋果;
只有finally和try操作的是同一個物件本身,比如類似map和list這種,操作的是籃子,才會互相影響。