當try、catch中有return時,finally中的代碼會執行么?


今天,看到一個面試題:

try-catch-finally 中,如果 catch 中 return 了,finally 還會執行嗎?

我們用代碼來驗證下:

    public static void main(String[] args) {
        System.out.println("我是輸出結果a:" + test1());
        

    public static int test1() {
        int a = 5;
        try {
            System.out.println(a / 0);
            a = 10;
        } catch (ArithmeticException e) {
            System.out.println("我是catch中的a:" + a);
            return a = 20;// 程序執行到這時,a=20已經執行完,准備好返回結果了,發現有finally,則在去執行finally
        } finally {
            System.out.println("我是finally中未重定義的a:" + a);
            a = 30;
            System.out.println("我是finally中重定義過的a:" + a);
        }
        return a;
    }

運行結果:

1 我是catch中的a:5
2 我是finally中未重定義的a:20
3 我是finally中重定義過的a:30
4 我是輸出結果a:20

從結果中可看出:即使catch中return了,finally中的代碼還是會執行。但是有個問題,明明結果顯示,經過finally代碼的執行,a已經是30了,返回結果為什么還是20?

我們再執行另外代碼:

 1     public static void main(String[] args) {
 2         System.out.println("我是輸出結果a:" + test1());
 3         
 4     }
 5 
 6     public static int test1() {
 7         int a = 5;
 8         try {
 9             System.out.println(a / 0);
10             a = 10;
11         } catch (ArithmeticException e) {
12             System.out.println("我是catch中的a:" + a);
13             return a = 20;// 程序執行到這時,a=20已經執行完,准備好返回結果了,發現有finally,則在去執行finally
14         } finally {
15             System.out.println("我是finally中未重定義的a:" + a);
16             a = 30;
17             System.out.println("我是finally中重定義過的a:" + a);
18             return a = 30;
19         }
20     }

運行結果:

1 我是catch中的a:5
2 我是finally中未重定義的a:20
3 我是finally中重定義過的a:30
4 我是輸出結果a:30

我們會發現,如果finally中有return,結果會根據finally中的結果返回,如果finally中沒有return,結果會按照catch的結果返回,但是不管怎么樣,都是會執行finally的代碼。

前面的例子是基本類型的,那我們看下引用類型是不是也這樣:

 1     public static User getName1(){
 2         User user = null;
 3         try {
 4             user = new User("張三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user = new User("李四");
 8             return user;
 9         } finally {
10             user = new User("王五");
11             //return user;
12         }
13     }

結果

User [name=李四]

再試下其他:

 1     public static User getName1(){
 2         User user = null;
 3         try {
 4             user = new User("張三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user = new User("李四");
 8             return user;
 9         } finally {
10             user = new User("王五");
11             return user;
12         }
13     }

結果:

1 User [name=王五]

額。。。。。。引用類型類型好像也是這樣的。

我們再看看:

 1     public static User getName2(){
 2         User user = null;
 3         try {
 4             user = new User("張三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user.setName("李四");
 8             return user;
 9         } finally {
10             user.setName("王五");
11             //return user;
12         }
13     }

結果如下:

User [name=王五]

額。。。。好像不對啊,不應該是李四嗎?

 1     public static User getName2(){
 2         User user = null;
 3         try {
 4             user = new User("張三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user.setName("李四");
 8             return user;
 9         } finally {
10             user.setName("王五");
11             return user;
12         }
13     }

結果:

User [name=王五]

引用類型好像有問題啊。。。。

其實可以這么理解:執行完catch內的代碼后,會把結果值暫時保存,然后執行finally中的代碼,如果finally中沒有return,則直接把保存的值返回。如果finally中有return,則值會被finally改變,再返回。

而如果finally中沒有return,返回的值好像也有部分出乎我們的意料。可以這樣理解吧,catch中的結果值會被final修飾,當final修飾一個基本數據類型時,表示該基本數據類型的值一旦在初始化后便不能發生變

化;如果final修飾一個引用類型時,則在對其初始化之后便不能再讓其指向其他對象了,但該引用所指向的對象的內容是可以發生變化的。

就那下面代碼來說明:

1 User u1 = new User("張三");
2 User u2 = new User("李四");
3 final User u3  = u1;
4 u3 = u2;//這行代碼會報編譯錯誤
5 System.out.println(u3);
6 u1.setName("王五");
7 System.out.println(u3);

第四行代碼會報編譯錯誤:The final local variable u3 cannot be assigned. It must be blank and not using a compound assignment

說明final修飾的不能改變引用對象,但是引用對象u1的值變化還是可以。

上面的代碼執行下:

User [name=張三]
User [name=王五]

現在可以看出 上面的代碼  user.setName("王五");和user = new User("王五"); 執行的結果為什么會不一樣,因為setname改變的是引用所指向的對象的內容,是可以的。= new User("王五"); 是改變了引用指向,是不可以的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM