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

Mat*_*der 4 java try-with-resources

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

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

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

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

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

tep*_*pic 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");
}
Run Code Online (Sandbox Code Playgroud)

使用Java SE 7实现更好的资源管理:超越语法糖.


Mar*_*eel 5

其实是可以的:

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

}
Run Code Online (Sandbox Code Playgroud)

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

One one = new One();
try (one) {
    //...
}
Run Code Online (Sandbox Code Playgroud)

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

在 try-with-resources 块之前创建资源可能会导致细微的错误,因为如果在您进入该块之前发生异常(例如,如果您在创建 aOne和进入 try-with-resources之间做了其他事情)堵塞)。

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

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