【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 **************/

猜你喜欢

转载自www.cnblogs.com/yadiel-cc/p/11296567.html