假设我有一个懒惰的可迭代实例,需要关闭以释放资源。如果我从一个方法返回它并在finally块中关闭它,那么在客户端使用它之前或之后会调用finally块吗?
例如:
public CloseableIterable<T> getStuff() {
CloseableIterable<T> iterable = fetchStuffFromSomewhere();
try {
return iterable;
} finally {
iterable.close();
}
}
注意:在这里的Java 6上,但我也对Java 7中的try-with-resources位如何处理这种情况感兴趣。
答案 0 :(得分:1)
finally
块将始终在try
块被视为已完成之前执行。
根据JLS, Section 14.17,返回声明
尝试将控制转移到包含它的方法的调用者;
和
前面的描述说“尝试转移控制”而不仅仅是“转移控制”,因为如果tryblock或catch子句包含return语句的方法或构造函数中有任何try语句(§14.20), 然后,在将控制转移到方法或构造函数的调用者之前,将按顺序执行那些try语句的任何finally子句,从最里面到最外层。突然完成finally子句可能会破坏由return语句启动的控制权转移。
(粗体强调我的)
也就是说,return
内的try
语句将在实际返回之前执行finally
块。因此,您的CloseableIterable
将在返回给调用方之前关闭。
对于“try-with-resources”,代码相当于try-catch-finally块,因此它应该表现相同。根据{{3}},
try-with-resources语句使用变量(称为资源)进行参数化,这些变量在执行try块之前初始化并在执行try块后以与它们初始化的相反顺序自动关闭。 / p>
也就是说,您在Java 1.7中使用“try-with-resources”编写的等效代码将是:
try (CloseableIterable<T> iterable = fetchStuffFromSomewhere()) {
return iterable;
}
...在将控制转移回方法的调用者之前,它仍会关闭它。
答案 1 :(得分:0)
finally块在return
语句之前执行。您必须让方法的客户端代码正确处理可迭代实例(使其成为方法合同的一部分并正确记录)。
此外,值得通过示例学习。在Java API中找到一个返回Closeable
的方法,然后转到它的源代码,看看它是如何处理的。