返回一个可关闭的迭代

时间:2014-03-07 23:20:24

标签: java java-6 iterable finally

假设我有一个懒惰的可迭代实例,需要关闭以释放资源。如果我从一个方法返回它并在finally块中关闭它,那么在客户端使用它之前或之后会调用finally块吗?

例如:

public CloseableIterable<T> getStuff() {
    CloseableIterable<T> iterable = fetchStuffFromSomewhere();
    try {
        return iterable;
    } finally {
        iterable.close();
    }
}

注意:在这里的Java 6上,但我也对Java 7中的try-with-resources位如何处理这种情况感兴趣。

2 个答案:

答案 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的方法,然后转到它的源代码,看看它是如何处理的。