在try中使用资源,使用之前创建的资源语句

时间:2016-12-18 08:04:18

标签: java try-with-resources

从Java 7开始,我们可以将try与资源一起使用:

try (One one = new One(); Two two = new Two()) {
    System.out.println("try");
} catch (Exception ex) { ... }

现在我的问题是,为什么我必须在try语句中创建对象?为什么我不允许在语句之前创建对象:

One one = new One();
try (one; Two two = new Two()) {
    System.out.println("try");
} catch (Exception ex) { ... }

我没有看到任何理由,为什么这应该是一个问题。虽然我收到错误消息"此语言级别不支持资源引用"。我将我的IDE(IntelliJ IDEA)设置为Java 8,因此应该可以工作。是否有充分的理由,不被允许?

3 个答案:

答案 0 :(得分:8)

您不必在try-with-resources语句中创建对象,您只需要声明一些实现AutoCloseable的类型的局部变量。这些变量实际上是最终的,并且限定在try块中,这允许编译器使用它们来生成清理所需的close样板。

FileInputStream f1 = new FileInputStream("test1.xml");
FileInputStream f2 = new FileInputStream("test2.xml");
// Don't need to create the resources here, just need to declare some vars
try (InputStream in1 = f1; InputStream in2 = f2) {
    // error; in1 is final
    in1 = new FileInputStream("t");
}

Better Resource Management with Java SE 7: Beyond Syntactic Sugar

答案 1 :(得分:3)

实际上可能是:

One one = new One();
try (One temp = one; ....;) {

}

从Java 9开始,您甚至不需要声明一个额外的变量,而是可以直接使用该变量:

One one = new One();
try (one) {
    //...
}

然而,在try-with-resources之前创建资源几乎没有充分的理由。这可能是try-with-resources块最初要求您在资源列表中声明一个新变量的原因(这也很容易强制该变量是最终的)。然而,语言设计者认为灵活性在这里更为重要。

在try-with-resources块之前创建资源可能会导致细微的错误,因为如果在您进入块之前发生异常,资源就无法正常关闭(例如,如果您在创建One之间执行其他操作并进入try-with-resources块。)

一般情况下,您应该没有理由在资源关闭后访问资源,因此您应该将范围限制为资源打开的时间(即try-with-resources块)。如果您确实需要在资源关闭后访问它,您可能需要考虑一种不同的设计,其中(可关闭的)资源与关闭资源后所需的对象/数据分开,或者您需要使用嵌套的尝试 - 资源块。

例外情况可能是,如果你传入AutoCloseable,你的方法必须保证它在退出时关闭,但这通常是一种设计气味:打开资源的那个也应该是负责关闭它。

答案 2 :(得分:1)

从Java 9开始,可以清除带有final引用的try-resource块,而无需在try块中重新声明变量。

例如,

final One one = new One();
try (one) {
    System.out.println("try");
} catch (Exception ex) { ... }

Source

  

允许有效最终变量在try-with-resources语句中用作资源。 Java SE 7中try-with-resources语句的最终版本要求为该语句管理的每个资源声明一个新鲜变量。这是该功能早期迭代的变化。 JSR 334的公共审阅草案讨论了对try-with-resource的早期审阅版本进行更改的理由,该版本允许使用该语句管理表达式。 JSR 334专家组赞成对try-with-resources进行进一步的改进:如果资源由最终变量或有效的最终变量引用,则try-with-resources语句可以管理资源而无需声明新变量。由try-with-resources语句管理的受限制的表达式避免了导致删除通用表达式支持的语义问题。专家组决定进行这种改进时,发布时间表中没有足够的时间来适应更改。