Java的try...catch...finally语句中finally部分的执行与否及执行时机探究

Java的try…catch…finally语句中finally部分的执行与否及执行时机探究

前言:

​在我们学习Java的异常处理时,一般有两种处理方式,一是通过try…catch…finally语句捕获异常,另一种方式则是通过throws关键字将异常抛出,通常我们视情况决定处理方式。

在捕获异常的try…catch…finally 语句中,我们可以将try的部分看做是if,如果有异常,则进行catch部分;而catch部分则像switch语句中的case1,case2,根据捕获的异常类型选择执行哪个catch部分;而最后的finally部分,一般情况下无论程序是否执行了catch部分,均会执行,但是它在什么时候才不会执行,以及它的执行时机,是很值得我们去搞明白的。

try语句中有return关键字:

​我们在学习Java时知道,return关键字有两个作用:

​ 1.返回方法指定类型的值或对象

​ 2.方法的结束

​那么,如果在try语句没有异常,且try语句中有return关键字,那么按照return会结束方法的作用来看,finally语句应该不会执行,但实际上,finally语句时会执行的,其执行时机为:

​return意味着方法的结束,此时方法会先产生一个返回值(即使返回的类型为void,也会准备一个返回值),我们将产生返回值的过程称为过程A;而后方法将返回值进行返回,我们将该过程称为过程B;而finally语句的执行过程称之为过程C,那么过程A、B、C的执行顺序为:

​ A——>C——>B

​也就是说,finally会执行,且执行时机为方法产生返回值与将返回值返回的操作之间,以下进行代码演示说明:

​首先我们自定义一个Person类,用于接下来的演示,并创建其无参和有参构造,及相应的getter和setter方法,如下图所示:

在这

接着新建另一个FinallyDemo,定义try…catch…finally语句如下:

在这里插入图片描述

而后我们运行main方法,得到运行结果如下:

在这里插入图片描述

从上图可以看出,最终得到的结果是22,也就是说,return部分操作结束了该方法,但是结束之前,finally依旧执行,且更改了返回值。

return返回的是什么?

前面我们有说到,return的作用除了结束方法,另外一个就是返回一个值或者对象,那么return具体是怎么操作的呢,结合上面finally语句执行时机,我们可以演示如下:

首先我们定义好try…catch…finally语句如下:

在这里插入图片描述

此时我们按照之前的操作,猜测最终结果应该为“22”,但是实际运行结果为“18”,如下图所示:

在这里插入图片描述

为什么会有这个差异呢?原因在于数据类型的不同,在第一次操作时,我们先定义了一个Person 类,return返回的也是Person类的实例化对象p,而第二次return的是一个基本数据类型int,而return的操作时先对要return的“东西”进行复制,但是在基本数据类型和引用数据类型上,它保留的副本是不一样的。

在这里插入图片描述

如上图,return的对象是引用数据类型时,由于return先复制它要返回的对象,也就是该对象的地址值,因此在接下来的finally语句执行将年龄改为22岁后,return执行返回操作,依据它所复制的地址值找到了对象所在的内存空间,但此时对象p的年龄已经被finally更改为22岁了。

打个比方,如果return的是引用数据类型,那么相当于服务员是先拿到了酒店的房间号,而finally在服务员到达房间之前,先对房间的内部物品进行了更改移动,因此后续服务员到达后所看到的房间就是被finally更改过布局的房间。

在这里插入图片描述

如上图所示,return返回基本数据类型的时候,我们可以理解为直接复制了等号右边的18,因此即使finally更改了a的值,return返回的依旧是18。

finally语句是否执行:

​首先先给出结论,finally语句除非程序非正常关闭,否则均会执行,所谓的非正常关闭,是指出现诸如电脑死机,电脑因为停电关机等硬件原因导致程序非正常关闭,或者在进行finally语句前已经执行了让JVM退出的指令(如System.exit()),否则finally语句必然执行。

在这里插入图片描述

由上图我们可以看到,在finally语句执行前,由于System.exit()命令执行,JVM停止运行,finally语句也因此未被执行。

总结:

try…catch…finally语句中的finally部分除非是电脑关机、停电等问题或程序被中途关闭,否则必定运行,在finally语句以外的部分存在return关键字的时候,尽管return会结束方法,但是finally会在return进行复制和return进行返回操作之间执行。