10.2.5 使用finally回收资源
10.2.5 使用finally回收资源
垃圾回收机制不会回收物理资源
Java的垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象所占用的内存。
try块中打开的物理资源由程序员显示回收
程序在try
块里打开了一些物理资源(例如数据库连接、网络连接和磁盘文件等),这些物理资源都必须显式回收。
不可以在try块或者catch块中回收物理资源
- 假设程序在
try
块里进行资源回收,如果try
块的某条语句引起了异常,该语句后的其他语句通常不会获得执行的机会,这将导致位于该语句之后的资源回收语句得不到执行。 - 如果在
catch
块里进行资源回收,但catch
块完全有可能得不到执行,这将导致不能及时回收这些物理资源。
finally块专门用来回收物理资源
为了保证一定能回收try
块中打开的物理资源,异常处理机制提供了finally
块。不管try
块中的代码是否出现异常,也不管哪一个catch
块被执行,甚至在try
块或catch
块中执行了return
语句, finally
块总会被执行。
finally
块总会被执行,即使在try
块或catch
块中执行了return
语句,finally
块依然被执行。
完整的java异常处理语法
完整的Java
异常处理语法结构如下:
1 | try |
try块必须出现 catch块和finally块可选
- 异常处理语法结构中只有
try
块是必需的,也就是说,如果没有try
块,则不能有后面的catch
块和finally
块; catch
块和finally
块都是可选的,但catch块和finally块至少出现其中之一,也可以同时出现;- 可以有多个
catch
块,捕获父类异常的catch
块必须位于捕获子类异常的后面; - 但不能只有
try
块,既没有catch
块,也没有finally
块; - 多个
catch
块必须位于try
块之后, finally
块必须位于所有的catch
块之后。
看如下程序。
1 | import java.io.*; |
即使try块 catch块中有return语句 finally块一样得到执行
上面程序的try
块后增加了finally
块,用于回收在try
块中打开的物理资源。注意程序的catch
块中1号代码处有一条return
语句,该语句强制方法返回。
在通常情况下,一旦在方法里执行到return
语句的地方,程序将立即结束该方法;
但在try
或catch
块中,虽然return
语句会强制结束方法,但一定会先执行finally
块里的代码。运行上面程序,看到如下结果:
1 | a.txt (系统找不到指定的文件。) |
上面运行结果表明方法返回之前还是执行了finally
块的代码。
如果异常处理代码中退出虚拟机 则finally将失去执行的机会
将1处的return
语句注释掉,取消2处代码的注释,即在异常处理的catch
块中使用System.exit(1)
语句来退出虚拟机。执行上面代码,看到如下结果:
1 | a.txt (系统找不到指定的文件。) |
上面执行结果表明finally
块没有被执行。如果在异常处理代码中使用System.exit()
语句来退出虚拟机,则finally
块将失去执行的机会。
除非在try
块,catch
块中调用了退出虛拟机的方法,finally
才会因为失去执行的机会,而得不到执行。否则不管在try
块、 catch
块中执行怎样的代码,出现怎样的情况,异常处理的finally
块总会被执行。
finally块的return,throw语句会覆盖try catch块的return throw
在通常情况下,不要在finally
块中使用如return
或throw
等导致方法终止的语句,一旦在finally
块中使用了return
或throw
语句,将会导致try
块、 catch
块中的return
、throw
语句失效。看如下程序。
1 | public class FinallyFlowTest |
上面程序在finally
块中定义了一个return false
语句,这将导致try
块中的return true
失去作用。运行上面程序,将打印出false
的结果。
try块或catch块中有return或throw语句的情况
当Java
程序执行try
块、 catch
块时遇到了return
或throw
语句,这两个语句都会导致该方法立即结束,但是系统执行这两个语句是会先去寻找该异常处理流程中是否包含finally
块。
- 如果没有
finally
块,程序立即执行return
或throw
语句,方法终止; - 如果有
finally
块,系统立即开始执行finally
块,只有当finally
块执行完成后,系统才会再次跳回来执行try
块、catch
块里的return
或throw
语句;- 如果
finally
块里也使用了return
或throw
等导致方法终止的语句,finally
块已经终止了方法,系统将不会跳回去执行try
块、catch
块里的任何代码。
- 如果
所以,尽量避免在fnly
块里使用 retur
或 throw
等导致方法终止的语句,否则可能出现