关于finally语句的一些小秘密

本文通过两个测试案例深入探讨了Java中finally块的执行时机,特别是在与return语句交互时的行为,为读者揭示了finally块如何确保在方法返回前执行。

     刚才在一个人的blog中看到一个关于java中的finally里的语句在什么时候执行的文章,感觉还是挺有收获的,现在就把他的大致意思以及自己的验证和大家分享下

    在java的API中,关于的finally的介绍是无论异常处理try-catch语句是否抛出异常,finally中的语句都会执行。因此我们可以在finally语句中做很多必须要做的操作,比如流关闭、链接关闭等。

    但是有个问题,如果try最后return语句,那finally里的语句又是什么时候去执行呢?

    这个问题先不回答,我们先看下面几个测试用例,看完之后也许你就知道了点什么。

 /**  
 *@Description: 关于finally的测试
 */ 
package cn.lulei.test;  
  
public class Test {
	
	public int testFinally(){
		int x = 1;
		try{
			return x;
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		} finally {
			x++;
			System.out.println("x = " + x);
		}
	}
	
	public static void main(String[] args) {
		System.out.println("testFinally:" + new Test().testFinally());
	}
}

 输出结果是:

x = 2

testFinally:1

 

 /**  
 *@Description: 关于finally的测试
 */ 
package cn.lulei.test;  
  
public class Test {
	
	@SuppressWarnings("finally")
	public int testFinally(){
		try{
			return function1();
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		} finally {
			return function2();
		}
	}
	
	private int function1(){
		System.out.println("function1");
		return 1;
	}
	private int function2(){
		System.out.println("function2");
		return 2;
	}
	
	public static void main(String[] args) {
		System.out.println("testFinally:" + new Test().testFinally());
	}
}

 输出结果是:

function1

function2

testFinally:2

 

    看完这两个测试用例,是不是感觉finally中的语句好在try中的return语句之前,又好像在try中的return语句之后。其实finally中的语句更确切的说是在return中间运行的,这里也许你会说,return语句明显就是一步,哪里来的中间,不错,是没有中间,但是如果从整体来看,也许就“有了”,下面就简单分析下:

    A函数调用B函数并得到结果的过程,就好比A函数准备好了一个空罐子,当B函数要返回结果时,先把结果放在罐子里①,然后再将程序逻辑返回到A函数②。所谓的返回,就是B函数说,我不运行了,你A函数继续运行吧。这时我们再回头看一下上面的测试用例,第一个没有什么好说的,B把1放到罐子里,又运行了若干操作,最后告诉A函数继续运行,所以得到上图的结果;第二个也是一样,B函数先把1放到罐子里,然后继续运行一些操作,这时B发现该把2放到罐子里的,因此又把罐子里的值换成2,最后告诉A函数继续运行,所以A函数得到的返回值是2而不是1。所以实际上,当罐子里面有值的时候,B并不是立即通知A,而是等finally里面的语句全部执行完之后,采去通知A的,这样解释return就相当于有中间了。

### C# 中 try-finally 语句的用法和工作机制 #### 1. 基本概念 `try-finally` 是 C# 中用于异常处理的一种结构。无论是否发生异常,`finally` 块中的代码都会被执行。这种机制确保了在执行某段代码时,无论结果如何,都可以执行重要的清理操作[^3]。 #### 2. 语法结构 `try-finally` 的基本语法如下: ```csharp try { // 可能引发异常的代码 } finally { // 必须执行的代码 } ``` #### 3. 工作机制 - `try` 块中包含可能引发异常的代码。 - 如果在 `try` 块中发生了异常且没有被捕获,则程序会跳转到 `finally` 块执行。 - 即使 `try` 块中的代码正常执行完毕,`finally` 块也会被执行。 - `finally` 块通常用于释放资源、关闭文件或数据库连接等操作[^4]。 #### 4. 示例代码 以下是一个使用 `try-finally` 的示例,展示了如何确保资源被正确释放: ```csharp public void ReadFile(string filePath) { System.IO.StreamReader file = null; try { file = new System.IO.StreamReader(filePath); Console.WriteLine(file.ReadToEnd()); } finally { if (file != null) { file.Close(); // 确保文件流被关闭 } } } ``` 在此示例中,无论文件读取是否成功,`finally` 块都会确保文件流被关闭[^4]。 #### 5. 异常与 `finally` 的关系 即使在 `try` 块中抛出了未捕获的异常,`finally` 块仍然会被执行。这保证了即使程序因异常而终止,关键的清理代码也能被执行[^1]。 #### 6. `try-catch-finally` 组合 当需要处理异常并同时执行清理操作时,可以结合 `catch` 和 `finally` 使用: ```csharp public int Divide(int a, int b) { try { return a / b; } catch (DivideByZeroException e) { Console.WriteLine("Error: Division by zero."); throw; // 重新抛出异常 } finally { Console.WriteLine("Finally block executed."); } } ``` 在这个例子中,`finally` 块会在任何情况下(包括异常)执行[^2]。 #### 7. 注意事项 - `finally` 块中的代码不应包含可能引发新异常的逻辑,以免干扰异常处理流程。 - 如果 `try` 块中存在 `return` 语句,`finally` 块仍会在方法返回前执行[^3]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值