Java异常处理中对于finally的一些思考

本文深入探讨Java中finally块的执行情况,包括其执行条件、时机及如何影响方法的返回值。通过多个代码示例,解析finally块在不同场景下的表现,揭示其在异常处理中的作用。

点击上方“程序猿技术大咖”,关注加群讨论

一、前言

因为这次面试有问到一些同学 finally 的问题,发现自己这块好像有点记不太清楚了,有的点可能还给人家说错了,一度弄得场面有些尴尬。所以说这篇文章深入研究一下 finally 的执行情况和返回值的情况。

二、finally一定会执行吗?

先给答案:肯定不是。

我们可以看两种情况:

1.在执行 try 块之前直接 return,我们发现 finally 块是不会执行的:
 1public class TryCatchTest {
 2
 3    private static int total() {
 4        int i = 11;
 5        if (i == 11) {
 6            return i;
 7        }
 8        try {
 9            System.out.println(执行try);
10        } finally {
11            System.out.println(执行finally);
12        }
13        return 0;
14    }
15
16    public static void main(String[] args) {
17        System.out.println(执行main: + total());
18    }
19}
20输出结果:
21执行main:11
2.在执行try块之前制造一个错误,直接爆红:
 1public class TryCatchTest {
 2
 3    private static int total() {
 4        return 1 / 0;
 5        try {
 6            System.out.println(执行try);  //这行爆红,原因就是无法访问
 7        } finally {
 8            System.out.println(执行finally);
 9        }
10        return 0;
11    }
12
13    public static void main(String[] args) {
14        System.out.println(执行main: + total());
15    }
16}

综上我们看出,如果程序连 try 块都执行不到,那么 finally 块自然就不会执行到了。

不过这里有的同学就会问:如果执行了 try 块,finally 块一定会执行吗?有的同学答案就是一定会,其实非然,看看下面的例子吧:

 1public class TryCatchTest {
 2
 3    private static int total() {
 4        try {
 5            System.out.println(执行try);
 6            System.exit(0);
 7        } catch (Exception e) {
 8            System.out.println(执行catch);
 9        } finally {
10            System.out.println(执行finally);
11        }
12        return 0;
13    }
14
15    public static void main(String[] args) {
16        System.out.println(执行main: + total());
17    }
18}
19输出结果:
20执行try

我们在执行 try 块之中退出 jvm,就没事了,都不执行了。当然这个情况是比较极端的,记住就行,没事不要乱整这个。最后总结一下:不管是给 try 块中造了个异常,还是在 try 块中进行 return,我们发现 finally 块还是会执行的。因为异常处理设计初衷就是让 finally 块始终执行。这个总结在 finally 的执行时机得到证明。

三、finally 执行时机探讨

首先看常规情况:

 1public class TryCatchTest {
 2
 3    private static int total() {
 4        try {
 5            System.out.println(执行try);
 6            return 11;
 7        } finally {
 8            System.out.println(执行finally);
 9        }
10    }
11
12    public static void main(String[] args) {
13        System.out.println(执行main: + total());
14    }
15}
16输出结果:
17    执行try
18    执行finally
19    执行main:11

同样的,finally 执行在 catch 块 return 的执行前。

四、finally 块中的返回值

1.finally 块不含返回值,但是做改变变量值的操作。
看一个例子:
 1public class TryCatchTest {
 2
 3    private static int total() {
 4        int i = 0;
 5        try {
 6            System.out.println(执行try: + i);
 7            return i;
 8        } finally {
 9            ++i;
10            System.out.println(执行finally: + i);
11        }
12    }
13
14    public static void main(String[] args) {
15        System.out.println(执行main: + total());
16    }
17}
18输出结果:
19执行try:0
20执行finally:1
21执行main:0

如果看完前面分析,会发现跟想象的不太一样。我们经过前面的分析,finally  块的执行时机应该是 return 之前,那理论上我们应该先 ++i 使得 i 等于 1,在执行return i; 自然会返回 1。可是结果却返回了 0,这是因为 Java 程序会把 try 或者 catch 块中的返回值保留,也就是暂时的确认了返回值,然后再去执行 finally 代码块中的语句。等到 finally 代码块执行完毕后,如果 finally 块中没有返回值的话,就把之前保留的返回值返回出去。

2.finally 中含有返回值。

示例1:

 1public class TryCatchTest {
 2
 3    private static int total() {
 4        try {
 5            System.out.println(执行try);
 6            return 1;
 7        } finally {
 8            System.out.println(执行finally);
 9            return 2;
10        }
11    }
12
13    public static void main(String[] args) {
14        System.out.println(执行main: + total());
15    }
16}
17输出结果:
18执行try
19执行finally
20执行main:2

示例2:

 1public class TryCatchTest {
 2
 3    private static int total() {
 4        int i = 1;
 5        try {
 6            System.out.println(执行try: + i);
 7            return i;
 8        } finally {
 9            ++i;
10            System.out.println(执行finally: + i);
11            return i;
12        }
13    }
14
15    public static void main(String[] args) {
16        System.out.println(执行main: + total());
17    }
18}
19输出结果:
20执行try:1
21执行finally:2
22执行main:2

示例3:

 1public class TryCatchTest {
 2
 3    private static int total() {
 4        int i = 1;
 5        try {
 6            System.out.println(执行try: + i);
 7           
 8        } finally {
 9            ++i;
10            System.out.println(执行finally: + i);
11        }
12        return i;
13    }
14
15    public static void main(String[] args) {
16        System.out.println(执行main: + total());
17    }
18}
19执行结果:
20执行try:1
21执行finally:2
22执行main:2

这三个示例都说明了一点,在分析含有 finally 块的方法返回值时,要对于 return 出现的地方进行具体分析。在 finally 块中进行 return 操作的话,则方法整体的返回值就是 finally 块中的 return 返回值。如果在 finally 块之后的方法内 return,则 return 的值就是进行完上面的操作后的 return 值。

喜欢就点个"在看"呗,留言、转发朋友圈

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值