【JavaSE】finally塊不被執行的情況總結


finally塊不被執行的情況總結


2019-08-03  22:23:02  by沖沖

 

finally塊的作用

通常用於處理善后工作。當try塊里出現異常時,會立即跳出try塊,到catch塊匹配對應的異常,執行catch塊里的語句。此時,可能在try塊里存在打開的文件沒關閉,連接的網絡沒斷開,這部分資源是GC所不能自動處理的,所以finally的作用就是將它們及時釋放回收。

finally塊不被執行的情況,總共有3種:不進入try塊、程序中止、線程中止(帶finally塊的是守護線程,其非守護線程都執行完畢)

 

1. 未執行try塊

對於try-catch-finally或者try-finally,如果不能進入try塊,則finally塊也無法進入。

 1 public class Test {
 2     public static void main(String[] args) {
 3         boolean flag = false;
 4         if(flag) {
 5           try {
 6               System.out.println("enter try block");
 7            } finally {
 8               System.out.println("enter finally block");
 9            }
10         }
11    }
12 }
13  /******************
14  控制台無輸出
15  *******************/

 

2. System.exit()

System.exit()的作用是中止當前虛擬機,如果虛擬機被中止,程序也會被終止,finally代碼塊自然不會執行。

 1 public class Test {
 2     public static void main(String[] args) {
 3        try {
 4             System.out.println("enter try block");
 5             System.exit();
 6        } finally {
 7             System.out.println("enter finally block");
 8        }
 9     }
10 }
11 /*****************
12 控制台打印如下
13 enter try block
14 ******************/

 

3. try塊陷入無限循環

 1 public class Test {
 2     public static void main(String[] args) {
 3        try {
 4             while(true){
 5                 System.out.println("enter try block");
 6             }
 7        } finally {
 8             System.out.println("enter finally block");
 9        }
10     }
11 }
12 /*****************
13  完蛋
14  *****************/

 

4. 守護(daemon)線程被中止時

Java線程分為兩類,守護線程和非守護線程。當所有的非守護線程都終止時,無論守護線程存不存在,虛擬機都會kill掉所有的守護線程從而中止程序。

虛擬機中,執行main方法的線程就是一個非守護線程,垃圾回收則是另一個守護線程,main執行完,則程序中止,而不管垃圾回收線程是否中止。

所以,如果守護線程中存在finally代碼塊,那么當所有的非守護線程中止時,守護線程被kill掉,其finally代碼塊是不會執行的。

 1 public class Test {
 2     public static void main(String[] args) {
 3         //main是一個非守護線程
 4         Thread thread = new Thread(new Task());
 5         thread.setDaemon(true); //設置thread為守護線程
 6         thread.start();
 7         TimeUnit.SECONDS.sleep(5); //阻塞5s.
 8     }
 9 }
10 class Task implements Runnable {
11     @Override
12     public void run() {
13          System.out.println("enter run()");
14         try {
15             System.out.println("enter try block");
16         } catch(InterruptedException e) {
17             System.out.println("enter catch block");
18         } finally {
19             System.out.println("enter finally block");
20         }      
21     }
22 }
23 /*******************
24 控制台打印如下
25 enter run()
26 enter try block
27 enter try finally block
28 ********************/

上述代碼,語句 TimeUnit.SECONDS.sleep(5); 會使main線程阻塞5秒,足夠線程thread執行。

如果將該語句注釋,非守護線程main線程執行完 thread.start(); 這行后,存在三種情況:①CPU時間片還是交給main線程,則非守護線程執行完畢,守護線程thread就會被終止,finally塊不執行;②CPU時間片交給thread線程,但是thread線程剛執行完try塊,就得交付時間片給main,main已經無語句執行,就會結束,導致守護線程thread也要結束,finally塊不執行;③CPU時間片交付thread線程,thread線程完全執行,finally塊被執行。

 

4. 其他迷惑性選項

(1)當try塊里面包含有break,該次try塊結束后,finally塊也會執行。

 1 public class Test {
 2     public static void main(String[] args) {
 3         for (int i = 0; i < 5; i++) {
 4             try {
 5                 if (i == 2) {
 6                     break;
 7                 }
 8             } finally {
 9                 System.out.print(i);
10             }
11         }
12     }
13 }
14 
15 /*************
16  輸出結果:012
17 **************/

(2)當try塊里面包含有return,該次try塊結束后,finally塊也會執行。

 1 public class Test {
 2     public static void main(String[] args) {
 3         for (int i = 0; i < 5; i++) {
 4             try {
 5                 if (i == 2) {
 6                     return;
 7                 }
 8             } finally {
 9                 System.out.print(i);
10             }
11         }
12     }
13 }
14 
15 /*************
16  輸出結果:012
17 **************/

(3)當try塊里面包含有continue,該次try塊結束后,finally塊也會執行。

 1 public class Test {
 2     public static void main(String[] args) {
 3         for (int i = 0; i < 5; i++) {
 4             try {
 5                 if (i == 2) {
 6                     continue;
 7                 }
 8             } finally {
 9                 System.out.print(i);
10             }
11         }
12     }
13 }
14 
15 /*************
16  輸出結果:01234
17 **************/

 


免責聲明!

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



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