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. 洛谷4219 BJOI2014大融合(LCT维护子树信息)

    QWQ 这个题目是LCT维护子树信息的经典应用 根据题目信息来看,对于一个这条边的两个端点各自的\(size\)乘起来,不过这个应该算呢? 我们可以考虑在LCT上多维护一个\(xv[i]\)表示\(i ...

  2. Go语言核心36讲(Go语言基础知识五)--学习笔记

    05 | 程序实体的那些事儿(中) 在前文中,我解释过代码块的含义.Go 语言的代码块是一层套一层的,就像大圆套小圆. 一个代码块可以有若干个子代码块:但对于每个代码块,最多只会有一个直接包含它的代码 ...

  3. 云原生的弹性 AI 训练系列之三:借助弹性伸缩的 Jupyter Notebook,大幅提高 GPU 利用率

    Jupyter Notebooks 在 Kubernetes 上部署往往需要绑定一张 GPU,而大多数时候 GPU 并没有被使用,因此利用率低下.为了解决这一问题,我们开源了 elastic-jupy ...

  4. 解决npm : 无法加载文件 D:\Code\renren-fast-vue\node_modules\.bin\npm.ps1,因为在......

    解决这个问题: 看看错误信息: npm : 无法加载文件 D:\DevPath\nodejs\npm.ps1,因为在此系统上禁止运行脚本.有关详细信息,请参阅 https:/go.microsoft. ...

  5. 2.2 DDD Layers & Clean Architecture DDD分层和简洁架构

    DDD Layers & Clean Architecture DDD分层和简洁架构 There are four fundamental layers of a Domain Driven ...

  6. SharkCTF2021 bbpop题记

    一道挺好的web. 做完这一题,感觉php序列化(甚至魔术方法)之类的有点开始玩明白了. 题面很长: 预备知识: PHP类的方法中,有一部分以下划线开头的"魔术方法".不同于普通方 ...

  7. 安装pytorch后import torch显示no module named 'torch'

    问题描述:在pycharm终端里通过pip指令安装pytorch,显示成功安装但是python程序和终端都无法使用pytorch,显示no module named 'torch'. 起因:电脑里有多 ...

  8. kivy画个半圆

    from kivy.uix.boxlayout import BoxLayout from kivy.app import App class BoxLayoutWidget(BoxLayout): ...

  9. 占位符,SQL注入?

    这两天在上课时被同学拿了一段代码问我,这段代码有什么问题,我看了一会说:Connection和PreparedStatement都没关.他说不止这方面的问题,还有sql注入的问题,我就坚决的说使用了占 ...

  10. [no_code][Alpha]事后分析

    $( "#cnblogs_post_body" ).catalog() 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们要解决的 ...