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. Ajax样例

    $.ajax({ url : "newsservlet",//请求地址 dataType : "json",//数据格式 type : "post&q ...

  2. Java并行任务框架Fork/Join

    Fork/Join是什么? Fork意思是分叉,Join为合并.Fork/Join是一个将任务分割并行运行,然后将最终结果合并成为大任务的结果的框架,父任务可以分割成若干个子任务,子任务可以继续分割, ...

  3. Shadertoy 教程 Part 1 - 介绍

    Note: This series blog was translated from Nathan Vaughn's Shaders Language Tutorial and has been au ...

  4. 【UE4】GAMES101 图形学作业4:贝塞尔曲线

    总览 Bézier 曲线是一种用于计算机图形学的参数曲线. 在本次作业中,你需要实现de Casteljau 算法来绘制由4 个控制点表示的Bézier 曲线(当你正确实现该算法时,你可以支持绘制由更 ...

  5. 剑指offer:JZ9 用两个栈实现队列

    JZ9 用两个栈实现队列 描述 用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能. 队列中的元素为int类型.保证操作合法,即保 ...

  6. ffmpeg剪视频

    ffmpeg裁剪合并视频   ffmpeg提供简单的命令参数: ffmpeg -ss START -t DURATION -i INPUT -vcodec copy -acodec copy OUTP ...

  7. Beta阶段第三次会议

    Beta阶段第三次会议 完成工作 姓名 工作 难度 完成度 ltx 1.掌握小程序代码和相关知识2.构思小程序游客模式 轻 90% xyq 1.修改场地表格信息2.对原页面活动申请场地部分进行修改 轻 ...

  8. Allure快速入门

    1.关于Allure     Allure框架是一个灵活轻量级多语言测试报告工具,它不仅可以以WEB的方式展示简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息.   ...

  9. Xpath语法学习记录

    高级参考:https://blog.csdn.net/wudaoshihun/article/details/82226122 举例: 1 <!DOCTYPE html> 2 <ht ...

  10. DC综合与Tcl语法结构概述

    转载:https://www.cnblogs.com/IClearner/p/6617207.html 1.逻辑综合的概述 synthesis = translation + logic optimi ...