为什么Java try-with-resource需要声明

时间:2012-12-12 09:21:40

标签: java try-catch

Java7的try-with-resources非常棒,但我无法理解为什么需要在try语句中包含资源声明。我的直觉说以下应该是可能的:

CloseableResource thing;
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
    // do some interesting things
}
thing.collectSomeStats();

唉,这会导致语法错误(隐藏地期望;)。将类型定义/声明移动到try语句中会起作用,这当然会将事物移动到相应的范围中。我想知道如何解决这个问题,当我想要更多来自AutoClosable而不是关闭时,我对为什么编译器需要它感兴趣。

3 个答案:

答案 0 :(得分:7)

您的版本未明确定义应关闭的内容,例如

CloseableResource thing;
Parameter a;

try (a = (thing = methodThatCreatesAThingAndDoesSomeSideEffect()).getParameter()) {

如果你写

该怎么办
try (12) {

还是什么?

同时

CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect();
CloseableResource thing2 = methodThatCreatesAThingAndDoesSomeSideEffect();

try(thing1) {
}

为什么只关闭thing1

因此,当前语法强制您同时打开关闭块来创建变量。

<强> ALSO2

CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect();

try(thing1) {
}

thing1.doSomethingOnClosedResource();

因为thing1仍然存在。

答案 1 :(得分:4)

Java 9 开始,您可以声明并初始化块外的 try-with-resources 中使用的变量。变量的唯一额外要求是它必须是effectively final 所以现在可以这样做:

CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect();
try (thing) {
    // do some interesting things
}
thing.collectSomeStats();

希望它有所帮助。

答案 2 :(得分:2)

阅读java规范我得出了这个结论(虽然它没有含蓄地表明):

他们让你声明变量并为它添加一个隐含的final,以确保你不能将变量重新绑定到其他地方。

在这种情况下,关闭资源是不可能的,因为它不再绑定到变量。

例如:

CloseableResource thing;
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
    thing = null;
    // thing can't be closed now
}

如果它在外面,我们可以让你使用final,但它有点难看。


解决方法: 如果要访问声明的资源,可以使用finally

try (CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect()) {
    // do some interesting things
} finally {
    thing.collectSomeStats();
}

请记住,最后thing已经关闭