【java解惑】try-finally语句执行问题

如下所示代码:

public class Example039 {

	public static void main(String[] args) {
		Example039 example039 = new Example039();
		System.out.println(example039.output1());
		example039.output2();
	}

	boolean output1() {
		try {
			// ...
			return true;
		} finally {
			return false;
		}
	}

	void output2() {
		try {
			System.out.println("执行try语句内容,然后exit,不正常退出");
			System.exit(0);
		} finally {
			System.out.println("这里的finally没有执行,因为exit了");
		}

	}
}

输出结果:

false
执行try语句内容,然后exit,不正常退出

程序分析:

在一个 try-finally 语句中,finally 语句块总是在控制权离开 try 语句块时执行的。无论 try 语句块是正常结束的,还是意外结束的,情况都是如此。当 try 语句块和 finally 语句块都意外结束时,在 try 语句块中引发意外结束的原因将被丢弃,而整个 try-finally 语句意外结束的原因将于 finally 语句块意外结束的原因相同。在output1中,在 try 语句块中的 return 语句所引发的意外结束将被丢弃,而 try-finally 语句意外结束是由 finally 语句块中的 return 造成的。 简单地讲,程序尝试着(try)返回(return)true,但是它最终(finally)返回(return)的是 false。

  每一个 finally 语句块都应该正常结束,除非抛出的是不受检查的异常。千万不要用一个 return、break、continue 或 throw 来退出一个 finally 语句块,并且千万不要允许将一个受检查的异常传播到一个 finally 语句块之外去。

    根据以上分析,对于output1的输出是很容易理解的。但是output2却给了一个上述分析相反的例子。

不论 try 语句块的执行是正常地还是意外地结束,finally 语句块确实都会执行。然而output2程序中,try 语句块根本就没有结束其执行过程。System.exit 方法将停止当前线程和所有其他当场死亡的线程。finally 子句的出现并不能给予线程继续去执行的特殊权限。

当 System.exit 被调用时,虚拟机在关闭前要执行两项清理工作。 首先,它执行所有的关闭挂钩操作,这些挂钩已经注册到了 Runtime.addShutdownHook 上。这对于释放 VM 之外的资源将很有帮助。务必要为那些必须在 VM 退出之前发生的行为关闭挂钩VM 执行在 System.exit 被调用时执行的第二个清理任务与终结器有关。

 总之, System.exit 将立即停止所有的程序线程,它并不会使 finally 语句块得到调用,但是它在停止 VM 之前会执行关闭挂钩操作。当 VM 被关闭时,请使用关闭挂钩来终止外部资源。通过调用 System.halt 可以在不执行关闭挂钩的情况下停止 VM,但是这个方法很少使用。



注:本【java解惑】系列均是博主阅读《java解惑》原书后将原书上的讲解和例子部分改编然后写成博文进行发布的。所有例子均亲自测试通过并共享在github上。通过这些例子激励自己惠及他人。同时本系列所有博文会同步发布在博主个人微信公众号搜索“爱题猿”或者“ape_it”方便大家阅读。如果文中有任何侵犯原作者权利的内容请及时告知博主以便及时删除如果读者对文中的内容有异议或者问题欢迎通过博客留言或者微信公众号留言等方式共同探讨。

源代码地址https://github.com/rocwinger/java-disabuse

时间: 2024-08-09 18:20:19

【java解惑】try-finally语句执行问题的相关文章

Java finally语句与return语句执行顺序解析

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

深入理解java:4.3.1. 框架编程之MyBatis---SQL语句执行的完整流程

Mybatis的整个的执行流程.如下图所示: 原理详解: MyBatis应用程序根据XML配置文件创建SqlSessionFactory, SqlSessionFactory在根据配置,配置来源于两个地方,一处是配置文件,一处是Java代码的注解,获取一个SqlSession. SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,用完之后关闭SqlSession. MyBatis的优缺点 优点: 1.简

《Java解惑》读书笔记

 摘选自<Java解惑>一书,之前整理了部分,一直没看完,最近为了督促自己每天读点这本书,决定一天至少更新一个谜题的内容,欢迎讨论. 欢迎关注技术博客http://blog.sina.com.cn/u/1822488043 Java解惑读书笔记 谜题1:奇数性 取余操作的定义: ( a / b ) * b + ( a % b ) = a 其中(a/b)是java运算的结果,也就是a/b是一个整数,比如3/2=1. 所以当取余操作返回一个非零结果的时候,它与左操作数具有相同符号. 请测试你的

【java解惑】输入输出流使用后及时关闭问题

如下所示代码: public class Example041 { public static void main(String[] args) throws IOException { Example041 e41 = new Example041(); e41.copy("d:\\微信名ape_it.txt", "d:\\微信名爱题猿.txt"); } private void copy(String src, String dest) throws IOExc

java中Finally块的执行

在try{}catch{}finally{}块中,都知道finally子块是肯定会执行的.当然也有个别情况,当在try{}或者catch{}块中出现强制退出System.exti(int)时,finally子块就不会执行了.这种情况不在今天的谈论范围以内. 看代码更加直观些: Java代码   package practice; public class FinallyRun { private int a = 0; public int getInt() { try { a = 1; retu

Java解惑 之 MySQL与JDBC编程

一.JDBC的常用接口和类: 1.DriverManager:主要用于管理JDBC驱动的服务类.在程序中使用该类的主要功能是获取Connection对象,该类包含如下方法: public static synchronized Connection getConnection(String url, String user, String password)  throws  SQLException:该方法获取数据库的连接. 2.Connection:代表数据库连接对象,而每一个Connect

《Java 解惑》笔记(一)

<Java 解惑>里都是一些编程时容易忽略的细节,却也蛮有意思的,所以将里面的内容稍作整理,简略地概括一下: 1.奇数性 在编程的时候经常会遇到要判断传进来的参数是否为奇数,而且容易惯性地认为判断余数是否为1即可,如下代码: public static boolean isOdd ( int i ) { return i % 2 == 1 } 这段程序在四分之一的时间里返回的都是错误的答案 因为在所有的 int 数值中,有一半都是负数,而 isOdd 方法对于对所有负奇数的判断都会失败.在任何

java解惑之常常忘记的事

java解惑之常常忘记的事 2012-10-17 18:38:57|  分类: JAVA |  标签:基础知识  软件开发  |举报|字号 订阅 针对刚接触java的菜鸟来说,java基础知识都是我们必须认真学习的,但是在工作过几年时间的老鸟来说,有时候也会对java的基础知识产生疑问,对于这种不确定,并且很容易混淆的知识点,java解惑已经为大家进行了很好的总结,现在借用一个作者的总结,进行一下罗列,希望能对你有所帮助. 1. 奇偶判断 不要使用 i % 2 == 1 来判断是否是奇数,因为i

oracle和java中的sql语句

在调试代码的时候遇到这样一个问题,程序运行到sql语句就抛invalid character异常,那我只好把sql语句拷出来,在oracle中执行一下,然而并没有什么错,这可难坏我了,这样都找不到错误,这到底是啥问题,摸不着头脑,一个老程序员提醒了我,在java中,sql语句的最后不能加分号,去掉之后可以正常执行了.虽然这是一个小问题,但我从来没注意过,以后就不会犯这低级错误了,哈哈.