Java语言中finally是否一定会执行你知道吗

目录
  • 简介
  • finally代码块不会运行的情况
    • 情况一:代码流程并未进入try语句块
    • 情况二:使用了System.exit(int)退出程序
    • 情况三:程序所在的线程死亡
    • 情况四:其它非正常退出
  • 总结

简介

我们都知道,finally 作为异常处理的一部分,它只能紧跟在try/catch语句后,附带一个语句块,表示这段语句,“在正常情况下”,最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。那么在我们的应用在运行中,一定会运行finally代码块吗?其实不是的,有以下几种情况我们的finally代码块是不会运行的。

finally 代码块不会运行的情况

情况一:代码流程并未进入try语句块

这也是最好理解的情况,如果代码流程不进入try代码块,则相应的catch和finally代码块自然不会执行。

	public static void main(String[] args) {
        int i = 0;
        System.out.println("enter main block");
        boolean flag = false;
        if (flag) {
            try {
                System.out.println("enter try block");
                i = i / i;
            } catch (Exception e) {
                System.out.println("enter catch block");
            }finally {
                System.out.println("enter finally block");
            }
        }
    }

运行结果为:

enter main block

情况二: 使用了 System.exit(int) 退出程序

在进入try或catch块后,使用了 System.exit(int) 退出程序。

	public static void main(String[] args) {
        int i = 0;
        System.out.println("enter main block");
        try {
            System.out.println("enter try block");
            System.exit(0);
            i = i / i;
        } catch (Exception e) {
            System.out.println("enter catch block");
        } finally {
            System.out.println("enter finally block");
        }
    }

public static void main(String[] args) {
        int i = 0;
        System.out.println("enter main block");
        try {
            System.out.println("enter try block");
            i = i / i;
        } catch (Exception e) {
            System.exit(0);
            System.out.println("enter catch block");
        } finally {
            System.out.println("enter finally block");
        }
    }

运行结果为:

enter main block
enter try block

但是呢,如果 System.exit(int) 在try代码块异常语句之后, finally 还是会被执行,因为已经没有机会执行 System.exit(int) ,程序已经退出了,比如:

	public static void main(String[] args) {
        int i = 0;
        System.out.println("enter main block");
        try {
            System.out.println("enter try block");
            i = i / i;
            System.exit(0);
        } catch (Exception e) {
            System.out.println("enter catch block");
        } finally {
            System.out.println("enter finally block");
        }
    }

运行结果为:

enter main block
enter try block
enter catch block
enter finally block

情况三:程序所在的线程死亡

在当前线程死亡的情况下,finally里的语句也不会执行,比如干扰中断,或者程序外部kill该线程,或者是意外中止。

	public static void main(String[] args) {
        int i = 0;
        System.out.println("enter main block");
        try {
            System.out.println("enter try block");
            // 模拟执行任务10s,然后在执行任务过程中杀死该线程
            Thread.sleep(10 * 1000);
            i = i / i;
        } catch (Exception e) {
            System.out.println("enter catch block");
        } finally {
            System.out.println("enter finally block");
        }
    }

这里在休眠里,用kill命令,杀死该线程,模拟非正常退出,最后运行结果为:

enter main block
enter try block

这里值得注意的是,我们常常在try语句块里获取了一些临界资源,然后finally语句块里释放该资源。此时,如果正常获得取资源后,程序非正常中断,则我们并未正常释放该资源,就会导致资源可能会被无限占用,所以这里要考虑一下其它的解决方法,比如给资源设置一个使用时间等,到期自动收回。

情况四:其它非正常退出

还有其它非正常退出(道理同上,就不演示了),也会导致finally代码块不执行,比如物理关闭电源,关闭 CPU等。这些其实在开发生产环境中是常有出现的,比如在开发中,某一台服务器获取锁后,不小心断电或宕机了(未成功释放锁),然后导致别的机器也不能获得到锁(如果锁无时间限制),最终导致出现系统型的问题。完事以后,你们开发也不知道发生了什么事,就把所有服务都重启了一次,解决了问题,最后说一句:“啊!还是重启大法好”。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java异常处理中同时有finally和return语句的执行问题

    在Java中当try.finally语句中包含return语句时,执行情况到底是怎样的,finally中的代码是否执行,大家众说纷纭,有的说会执行,有的说不会执行,到底哪种说法正确,现在通过下面的例子加以说明:      第一种情况:try中包含return语句,finally中不包含 public class TestTry { static String s=""; public static void main(String args[]){ s = test1(); Syste

  • java异常处理执行顺序详解try catch finally

    目录 不含return的执行顺序 finally子句 含return的执行顺序 返回类型是对象类型时值的变化 结论 不含return的执行顺序 执行顺序为执行try中代码,如果没有异常,然后执行try catch后续的代码.如: public static void main(String[] args) { try { int j = 10 / 2; System.out.println("执行try中代码!"); } catch (Exception e) { e.printSta

  • Java如果在try里面执行return还会不会执行finally

    前言 我们都知道,finally在捕获异常的操作中,总是最后并且一定会执行的.那么,如果我在使用try finally的时候,如果try 给了一个return,那么还会不会执行finally呢?这里就来试一试 finally Finally代码不管有没有异常发生它都会执行. 没有异常发生的时候,在try内的代码执行结束后,执行finally. 如果发生了异常并且给catch捕获,则在执行完catch之后执行finally. 如果有异常且未被捕获,则在异常被抛给上层之前执行. 事实上,不用try

  • 浅谈Java finally语句到底是在return之前还是之后执行(必看篇)

    网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下finally语句是不会被执行的: (1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到. (2)在try块中有System.exit(0);这样的语句,System.exit(0);

  • 完全解析Java编程中finally语句的执行原理

    可不能小看这个简单的 finally,看似简单的问题背后,却隐藏了无数的玄机.接下来我就带您一步一步的揭开这个 finally 的神秘面纱. 问题分析 首先来问大家一个问题:finally 语句块一定会执行吗? 很多人都认为 finally 语句块是肯定要执行的,其中也包括一些很有经验的 Java 程序员.可惜并不像大多人所认为的那样,对于这个问题,答案当然是否定的,我们先来看下面这个例子. 清单 1. public class Test { public static void main(St

  • Java语言中finally是否一定会执行你知道吗

    目录 简介 finally代码块不会运行的情况 情况一:代码流程并未进入try语句块 情况二:使用了System.exit(int)退出程序 情况三:程序所在的线程死亡 情况四:其它非正常退出 总结 简介 我们都知道,finally 作为异常处理的一部分,它只能紧跟在try/catch语句后,附带一个语句块,表示这段语句,“在正常情况下”,最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下.那么在我们的应用在运行中,一定会运行finally代码块吗?其实不是的,有以下几种情况

  • Java语言中flush()函数作用及使用方法详解

    最近在学习io流,发现每次都会出现flush()函数,查了一下其作用,起作用主要如下 //------–flush()的作用--------– 笼统且错误的回答: 缓冲区中的数据保存直到缓冲区满后才写出,也可以使用flush方法将缓冲区中的数据强制写出或使用close()方法关闭流,关闭流之前,缓冲输出流将缓冲区数据一次性写出.flash()和close()都使数据强制写出,所以两种结果是一样的,如果都不写的话,会发现不能成功写出 针对上述回答,给出了精准的回答 FileOutPutStream

  • Java语言中cas指令的无锁编程实现实例

    最开始接触到相关的内容应该是从volatile关键字开始的吧,知道它可以保证变量的可见性,而且利用它可以实现读与写的原子操作...但是要实现一些复合的操作volatile就无能为力了...最典型的代表是递增和递减的操作.... 我们知道,在并发的环境下,要实现数据的一致性,最简单的方式就是加锁,保证同一时刻只有一个线程可以对数据进行操作....例如一个计数器,我们可以用如下的方式来实现: public class Counter { private volatile int a = 0; pub

  • 在C#和Java语言中for和foreach的区别详解

    for循环和foreach循环的区别 首先在这里声明一点,C#和Java这两种语言很相似,尤其是初学的数据类型那一部分,所以这里写的for和foreach的区别在C#和Java中都适用. 我会在下面分别列出两种语言的for和foreach分别循环打印一个数组,大家可以看看区别 话不多说,直接上代码: //c# //先创建一个数组 int[] arr = new int[3] {99, 11, 22}; //利用for循环打印(可以创建一个变量 i;判断这个i是否小于数组的长度;每次循环i自增1)

  • Java 语言中Object 类和System 类详解

    Object是java所有类的基类,是整个类继承结构的顶端,也是最抽象的一个类.大家天天都在使用toString().equals().hashCode().waite().notify().getClass()等方法,或许都没有意识到是Object的方法,也没有去看Object还有哪些方法以及思考为什么这些方法要放到Object中. 一.Java Object类简介-所有类的超类 Object 是 Java 类库中的一个特殊类,也是所有类的父类.也就是说,J ava 允许把任何类型的对象赋给

  • C语言中system()执行cmd命令打开关闭程序的方法

    函数原型: int system(char *command); 使用该函数需要添加<stdlib.h>头文件 1.打开程序 系统自带程序可直接使用start命令 system("start iexplore.exe"); //启动ie 非系统自带程序需要加入路径 system("start D:\Tencent\WeChat\WeChat.exe"); //启动改路径下的客户端 注意如果路径中有空格,需要对整个路径添加双引号 2.关闭程序 system

  • go语言中if语句用法实例

    本文实例讲述了go语言中if语句用法.分享给大家供大家参考.具体分析如下: if 语句看起来跟 C 或者 Java 中的一样,除了没有了 ( ) 之外(甚至强制不能使用它们),而 { } 是必须的. 复制代码 代码如下: package main import (     "fmt"     "math" ) func sqrt(x float64) string {     if x < 0 {         return sqrt(-x) + "

  • Ruby语言中的String深入理解

    Ruby语言中的String是mutable的,不像java.C#中的String是immutable的.比如 复制代码 代码如下: str1="abc" str2="abc" 在java中,对于字面量的字符串,jvm内部维持一张表,因此如果在java中,str1和str2是同一个String对象.而在Ruby中, str1和str2是完全不同的对象.同样,在java中对于String对象的操作都将产生一个新的对象,而Ruby则是操纵同一个对象,比如: 复制代码 代

  • C语言中static的作用及C语言中使用静态函数有何好处

    想了解Java中static关键字的作用和用法详细介绍,请点击此处了解详情. 在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条,分别是: 一是隐藏功能,对于static修饰的函数和全局变量而言 二是保持持久性功能,对于static修饰的局部变量而言. 三是因为存放在静态区,全局和局部的static修饰的变量,都默认初始化为0 下面我逐一给大家介绍: (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有

  • go语言中iota和左移右移的使用说明

    在go语言中iota比较特殊,是一个被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字就会自动加1 左移运算符"<<"是双目运算符 左移n位就是乘以2的n次方. 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0. 右移运算符">>"是双目运算符

随机推荐