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

【JavaSE】finally块不被执行的情况总结的更多相关文章

  1. finally代码块不被执行的情况总结

    以前跟别人讨论finally关键字,我总是简单的说:“fianly代码块中的代码一定会执行,一般用来清除IO资源等非内存资源(内存资源由GC机制回收)”. 今天翻书发现了几种不会执行的情况,现在总结下 ...

  2. try-catch- finally块中, finally块唯一不执行的情况是什么?

    除非在try块或者catch块中调用了退出虚拟机的方法(即System.exit(1);),否则不管在try块.catch块中执行怎样的代码,出现怎样的情况,异常处理的finally块总是会被执行的 ...

  3. 触发Full GC执行的情况

    除直接调用System.gc外,触发Full GC执行的情况有如下四种. 1. 旧生代空间不足 旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然 ...

  4. Java 静态语句块、语句块、构造函数执行顺序

    class Parent{ static String name = "hello"; { System.out.println("3 parent block" ...

  5. oracle 查看某session的历史执行sql情况

    1. 查看性能最差的前100sql SELECT * FROM ( SELECT PARSING_USER_ID EXECUTIONS,SORTS,COMMAND_TYPE,DISK_READS,sq ...

  6. Java静态语句块、语句块、构造方法执行顺序

    package com.imooc.practice; class Parent{ public Parent(){ System.out.println("Parent构造方法执行!&qu ...

  7. java学习(一)静态代码块 构造代码块 构造方法的执行顺序及注意问题

    今天我总结了一下java中静态代码块 构造代码块 构造方法的执行顺序及其注意问题 首先要知道静态代码块是随着类的加载而加载,而构造代码块和构造方法都是随着对象的创建而加载 当时做了这么一个小案例(想必 ...

  8. 触发Full GC执行的情况 以及其它补充信息

    除直接调用System.gc外,触发Full GC执行的情况有如下四种.1. 旧生代空间不足旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然不足 ...

  9. “全栈2019”Java异常第二十一章:finally不被执行的情况

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

随机推荐

  1. 宙斯盾 DDoS 防护系统“降本增效”的云原生实践

    作者 tomdu,腾讯云高级工程师,主要负责宙斯盾安全防护系统管控中心架构设计和后台开发工作. 导语 宙斯盾 DDoS 防护系统作为公司级网络安全产品,为各类业务提供专业可靠的 DDoS/CC 攻击防 ...

  2. ShutdownHook原理

    微信搜索"捉虫大师",点赞.关注是对我最大的鼓励 ShutdownHook介绍 在java程序中,很容易在进程结束时添加一个钩子,即ShutdownHook.通常在程序启动时加入以 ...

  3. 【Python从入门到精通】(二)怎么运行Python呢?有哪些好的开发工具(PyCharm)

    您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 这是Pyhon系列文章的第二篇,本文主要介绍如何运行Python程序以及安装PyCharm开发工具. 干货满满,建议收藏,需要用到时常看看. 小伙 ...

  4. Java:String对象小记

    Java:String对象小记 对 Java 中的 String 对象,做一个微不足道的小小小小记 字节和字符的区别 字节 byte: 一个字节包含8个位(bit),因此byte的取值范围为-128~ ...

  5. 热身 for computer industry

    项目 内容 作业属于 班级博客 作业要求 作业要求 个人课程目标 掌握软件工程基础知识 具体有助方面 个人认知与规划 其他参考文献 博客Ⅰ 博客 Ⅱ 选择计算机 你为什么选择计算机专业?你认为你的条件 ...

  6. series和读取外部数据

    1.为什么学习pandas 我们并不是不愿意学习新的知识,只是在学习之前我们更想知道学习他们能够帮助我们解决什么问题.--伟哥 numpy虽然能够帮助我们处理数值,但是pandas除了处理数值之外(基 ...

  7. 字符串与模式匹配算法(二):MP算法

    一.MP算法介绍 MP 算法(Morris-Pratt算法)是一种快速串匹配算法,它是詹姆斯·莫里斯(James Morris)和沃恩·普莱特(Vaughan Pratt)在1970年提出的一种快速匹 ...

  8. docker的集群管理工具

    docker 集群管理三剑客: docker compose: Compose 是用于定义和运行多容器 Docker 应用程序的工具.通过 Compose,您可以使用 YML 文件来配置应用程序需要的 ...

  9. docker 简单总结

    一.docker 安装 yum 方式在centos和rhce上的安装条件: 要安装Docker引擎,你需要一个维护版本的CentOS 7或8.不支持或测试存档版本.必须启用centos-extras存 ...

  10. float32 和 float64

    float32 和 float64 Go语言中提供了两种精度的浮点数 float32 和 float64. float32,也即我们常说的单精度,存储占用4个字节,也即4*8=32位,其中1位用来符号 ...