finally語句到底在return之前還是之後執行?

finally語句的執行有一定前提,需執行到try語句。如果在try語句之前就返回,finally語句必然不會執行。此外,在執行try語句過程中,終止JVM也不會執行finally語句。所以,在finally語句塊執行的前提下,討論finally語句到底在return之前還是之後呢? 在這裏分了以下幾種情況來分析:

1.情況1,就是try中的return語句先執行但並沒有立即返回,其次finally塊中的語句執行,最後try中return返回。

public class Test {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test(){
        int num = 10;
        try {
            System.out.println("try doing...");
            return num += 10;
        }catch (Exception e){
            System.out.println("catch doing...");
        }finally {
            System.out.println("finally doing...");
            if (num > 15){
                System.out.println("num > 15, num = " + num);
            }
        }
        return 100;  //不可達
    }
}

運行結果:

try doing...
finally doing...
num > 15, num = 20
20

其過程是,try中的return語句num += 10先執行,num = 20,但該return語句沒有將結果直接返回,而是執行finally語句塊的語句,打印“finally doing…”,以及if語句打印“num > 15, num = 20”,執行完finally塊內容。最後,return返回try中的結果。(在此說下,Java中到底是傳值還是傳址?詳情見)

2.情況2,finally中的return語句會覆蓋try中return的結果

public class Test {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test(){
        int num = 10;
        try {
            System.out.println("try doing...");
            return num += 10;
        }catch (Exception e){
            System.out.println("catch doing...");
        }finally {
            System.out.println("finally doing...");
            if (num > 15){
                System.out.println("num > 15, num = " + num);
            }
            return 30;
        }
    }
}

運行結果:

try doing...
finally doing...
num > 15, num = 20
30

其過程是,try中的return語句num += 10依舊先執行,num = 20,該return語句沒有將結果直接返回,繼續執行finally語句塊的語句,打印“finally doing…”,以及if語句打印“num > 15, num = 20”,後執行finally中的return語句並將30作爲結果返回,從而造成了try中返回的結果num=20被覆蓋。

3.情況3,如果finally語句中沒有return語句覆蓋返回值,那麼原來的返回值是否會改變?

其實這與Java參數傳遞方式是相似的(均爲值傳遞),“返回值”均不會改變,這裏的“返回值”有兩層含義

如果返回的是基本數據類型,沒有return語句覆蓋返回值時,原來的返回值不會改變。注意,此處的返回值指的是 try語句塊 中變量num所指向的存儲單元的內容。(num = 20,返回的是20)。

public class Test {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test(){
        int num = 10;
        try {
            System.out.println("try doing...");
            return num += 10;  //返回的是num所對應存儲單元的內容,即20
        }catch (Exception e){
            System.out.println("catch doing...");
        }finally {
            System.out.println("finally doing...");
            if (num > 15){
                System.out.println("num > 15, num = " + num);
            }
            num = 100;
            System.out.println(num);
        }
        return 0;
    }
}

運行結果:

try doing...
finally doing...
num > 15, num = 20
100
20

返回的是引用數據類型,沒有return語句覆蓋返回值時,原來的返回值也不會改變。注意,此處的返回值指的是 try語句塊中 引用變量sb所指向的存儲單元的內容,內容是對象的地址值

public class Test {
    public static void main(String[] args) {
        System.out.println(test().toString()); //4. 訪問的是0x0001所指的對象
    }
    public static StringBuffer test(){
        StringBuffer sb = new StringBuffer("Kyrie");//1. 假設0x0001是創建的對象地址值
        try {
            System.out.println("try doing...");
            return sb;  //2. sb->0x0001,返回的是sb所對應存儲單元的內容,即0x0001
        }catch (Exception e){
            System.out.println("catch doing...");
        }finally {
            System.out.println("finally doing...");
            sb.append("2011");
            sb = new StringBuffer("6666");  //3. 此處,相當於sb指向了一個新對象,新對象的地址值爲0x1000,那麼sb所指存儲單元內容爲0x1000
            System.out.println(sb.toString());
        }
        return null;
    }
}

運行結果:

try doing...
finally doing...
6666
Kyrie2011

4.情況4,try塊裏的return語句在異常的情況下不會被執行

public class Test{
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test(){
        int num = 10;
        try {
            System.out.println("doing try。。。");
            num = num / 0;
            return num += 100;  //不會被執行
        }catch (Exception e){
            num += 10;
            System.out.println("doing catch, num = " + num);
        }finally {
            if (num > 15){
                System.out.println(" num > 15, num = " + num);
            }
        }
        return -1;
    }
}

運行結果:

doing try。。。
doing catch, num = 20
 num > 15, num = 20
-1

從上述結果可看出,try中發生的異常時,try中的return語句不會被執行。

5.情況5,當發生異常後,catch中的return執行情況與未發生異常時try中return的執行情況完全一樣

public class Test {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test(){
        int num = 10;
        try {
            System.out.println("doing try。。。");
            num = num / 0;
            return num += 100;
        }catch (Exception e){
            System.out.println("doing catch, num = " + num);
            return num += 40; //先執行 num+=40,此時num所指向的存儲單元的內容爲40
        }finally {
            if (num > 15){
                System.out.println(" num > 15, num = " + num);
            }
            num += 1000;
        }
    }
}

運行結果:

doing try。。。
doing catch, num = 10
 num > 15, num = 50
50

過程是發生異常後,catch中的return語句先執行,確定了返回值後再去執行finally塊,執行完後catch中的return再返回結果,finally裏對num的改變對返回值無影響,原因同前面一樣,也就是說情況與try中的return語句執行完全一樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章