文档章节

Java Magic. Part 3: Finally

qiujiayu
 qiujiayu
发布于 2016/07/25 16:47
字数 553
阅读 8
收藏 0

Every experienced java programmer should know that finally block always executed. But is it true?

It depends on our definition of program execution. But, generally speaking, yes.

Normal program execution

Aha, look at this, someone might retort:

try {
  System.exit(1);
} finally {
  System.out.println("I'm here, man");
}

You just said, finally block always executed?

Well. In that case no, because we speaking about normal flow of program execution. This is abnormal.

From the official tutorial

Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute.

Your counter question might be: If second line of that code always exectued?

System.out.println("Line 1");
System.out.println("Line 2");
System.out.println("Line 3");

Sure, because it's linear flow. Nothing can break...BANG...Electricity unavailable. Program stopped.

What about this? It's also abnormal program execution, and we can't guarantee anything for 100%. In fact, this is the same as System.exit(1) or reset button on your computer or whatever.

That's why, we are talking about normal program execution. Only normal.

I said yes? I meant no!

Perpetuum Mobile

Consider the following code:

try {
  while (true) {
    System.out.println("I print here some useful information");
  }
} finally {
  System.out.println("Let me run");
}

Will be the line "Let me run" printed? Maybe yes, if printing error to standard output appear. Almost always the answer is no.

In that case, there are no difference between simple statement and finally block. None of them will be executed, throw this example away.

Threads

What about threads? We know that execution flow controlled by threads and they can be interrupted.

Assume that we have thread that perform some work, and other thread kills first one right before finally block. Finally wasn't executed.

Assume that we have deadlock between two threads, right before finally line. The same thing.

From the same tutorial

...if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.

So, we can treat thread like a program, and make one effective rule:

Rule 1. Finally executes always, except the case where controlling program or thread was aborted.

Finally we return

Ok, now we know when finally is not executed. But do we know when finally is executed?

Consider the example:

int someFunc() {
  try {
    return 0;
  } finally {
    return 1;
  }
}

The result is obviously 1. Just because finally is always executed.

Consider, next example:

int someFunc() {
  try {
    throw new RuntimeException();
  } finally {
    return 1;
  }
}

The result is 1 again. And it's a problem. We just lose the exception. Such issue known as exception swallowing. It is very dangerous, because client's code expect either exception or some value, but it always get only value.

One more less imaginary example.

String deposit(int amount) throws DAOException {
  try {
    return dao.deposit(amount);
  } finally {
    return "OK";
  }
}

The logic behind finally is to have some default value, and our deposit method throws the DAOExceptionwhere client code is responsible for its handling. Unfortunately, perhaps compiler forces you to handle thisDAOException it never occurs. And string "OK" will be returned.

Rule 2. Never use return from finally block.

Instead of conclusion

A lot of programmers are aware about this common mistake. But some are not. Maybe these two simple rules give you a tiny light on coward finally.

本文转载自:http://mishadoff.com/blog/java-magic-part-3-finally/

qiujiayu
粉丝 53
博文 29
码字总数 12610
作品 1
东城
架构师
私信 提问
06-《深度拆解JVM》之JVM是如何处理异常的?

一、问题引入 今天我们来讨论下 Java 虚拟机的异常处理。众所周知,异常处理的两大组成要素是抛出异常和捕获异常。这两大要素共同实现程序控制流的非正常转移。 抛出异常可分为显式和隐式两种...

飞鱼说编程
2018/09/28
0
2
异常处理——finally的特点、作用及面试题

finally的特点: (1) 是异常处理的一部分,用于释放资源; (2) 一般来说,被finally控制的代码一定会执行; (3) 特殊情况:如果在执行到finally之前jvm退出了(比如:System.exit(0),但是,...

G_66_hero
2018/09/12
0
0
Jikes RVM 3.1.3 发布,研究虚拟机

Jikes RVM 3.1.3 包含一些增强和 bug 修复,如新的单元测试框架,修复了使用 Java 6/7 host JVM 构建 Jikes RVM 的问题,源码的清理等待。 Jikes研究虚拟机(Jikes Research Virtual Machin...

oschina
2013/02/13
794
3
java使用原生jdbc连接数据库并操作

使用Java连接数据库需要使用JDBC驱动。JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的...

hasagei
01/23
0
0
JAVA final finally finalize区别

简单区别: 中等区别: 虽然这三个单词在Java中都存在,但是并没有太多关联: final:java中的关键字,修饰符。 1.如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被...

qq22734179
2014/03/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

高并发场景下的缓存有哪些常见的问题?

一、缓存一致性问题 当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中的数据也保持一致,不能出现差异现象。 这就比较依赖缓存的过期和更新...

别打我会飞
39分钟前
3
0
List list = new ArrayList()为何父类引用指向子类对象(多态)

态:要有继承,方法的重写,父类引用指向子类对象 疑问一:父类引用指向子类对象 与指向父类对象 Animal cat = new Cat(); //向上转型。 父类引用指向子类对象,该引用不能再访问子类新增加的...

architect刘源源
39分钟前
3
0
分而治之-快速排序

快速排序的思想: 快速排序首先在数组中确定1个枢纽项(比如数组中的第一个元素),将大于该枢纽项的元素放到右侧,小于该枢纽项的元素放到左侧,这样枢纽项将数组划分成两部分。接着继续对划...

万山红遍
今天
5
0
Qt编写自定义控件9-导航按钮控件

前言 导航按钮控件,主要用于各种漂亮精美的导航条,我们经常在web中看到导航条都非常精美,都是html+css+js实现的,还自带动画过度效果,Qt提供的qss其实也是无敌的,支持基本上所有的CSS2属...

飞扬青云
今天
4
0
Python开发工具:pyJasper

原文:https://www.oschina.net/p/pyjasper 前言 pyJasper是 JasperReports 网络服务器的 Python 客户端。 pyJasper 是一组 Python 基础工具,可以用来处理 JasperReports 报表 。因为 Jasper...

A_裙232550246
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部