java中finally语句块注意事项

 我在程序中使用TarArchiveOutputStream对多个文件进行打包,finally语句块中调用了它的close方法关闭输出流。昨天碰到了一个很诡异的问题,执行到finally语句块抛出异常。按正常处理逻辑,文件打包会正常完成,finally中是不会出现异常的。然后就开始定位为什么会出现这样的异常,最终发现是因为打包过程中进行了额外的检查,如果条件不符合就抛出异常,然后进入到finally语句块。因为打包被异常中断,导致close出现异常,而finally中的异常会覆盖try语句中的异常,这就是我们定位这个文件花了较长时间的原因。我们用一个简单的测试代码来重现和说明这个现象:
1. public class Test {
2.         public static void main(String[] args) {
3.                 int x = 1;
4.                 int y = 0;
5.                 int z;
6.                 try {
7.                         z = (100 * x) / y;
8.                         System.out.println("z=" + z);
9.                 } finally {
10.                         z = x / y;
11.                         System.out.println("z=" + z);
12.                 }
13.         }
14. }
可以看到第7行和第10行都会出现被0除的异常。
执行以上代码的输出结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
          at Test.main(Test.java:10)
可以看到没有打印出第7行抛出异常时的调用堆栈。这是为什么呢?
第7行抛出异常后,进入第9行开始的finally语句块,finally语句块中的第10行也出现了异常,导致前面的异常被覆盖掉,因此最后打印出的异常调用堆栈是第10行的。
解决方法,捕获finally中可能出现的异常,修改后代码为:
1. public class Test {
2.         public static void main(String[] args) {
3.                 int x = 1;
4.                 int y = 0;
5.                 int z;
6.                 try {
7.                         z = (100 * x) / y;
8.                         System.out.println("z=" + z);
9.                 } finally {
10               try {
11.                 z = x / y;
12.                 System.out.println("z=" + z);
13.               } catch(Exception ex) {
14.                   ex.printStackTrace();
15.               }
16.                 }
17.         }
18. }

执行时的输出为:
java.lang.ArithmeticException: / by zero
          at Test.main(Test.java:11)
Exception in thread "main" java.lang.ArithmeticException: / by zero
          at Test.main(Test.java:7)
可见,这时try语句中的异常信息也出来了。

总结一下,finally中的语句,如果可能出现异常,一定要catch。
另外一个规范的做法,不要在finally中return一个返回值。具体原因是什么,请各位仔细思考一下,相信会想明白的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值