Java7 try-with-resources语句优势

50 java java-7

我正在寻找Java7的新功能.我发现一个是 try-with-resources Statement.任何人都可以告诉我它究竟意味着什么?我们应该使用它的原因和位置,以及我们可以利用此功能的地方?即使是try声明也没有catch阻止让我感到困惑.

mor*_*ano 75

它的引入是因为Java中使用的一些资源(如SQL连接或流)难以正确处理; 例如,在java 6中正确处理InputStream你必须做类似的事情:

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}
Run Code Online (Sandbox Code Playgroud)

你注意到丑陋的双重尝试吗?现在使用try-with-resources可以执行以下操作:

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}
Run Code Online (Sandbox Code Playgroud)

并且会自动调用close(),如果它抛出IOException,它将被抑制(如Java语言规范14.20.3中所指定).同样的情况发生了java.sql.Connection中


Ank*_*thi 15

文档中所述:

try-with-resources语句是一个声明一个或多个资源的try语句.资源是在程序完成后必须关闭的对象.try-with-resources语句确保在语句结束时关闭每个资源.实现的任何对象(java.lang.AutoCloseable包括实现的所有对象)java.io.Closeable都可以用作资源.

以下示例从文件中读取第一行.它使用BufferedReader实例从文件中读取数据.BufferedReader是一个在程序完成后必须关闭的资源:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,try-with-resources语句中声明的资源是BufferedReader.声明语句出现在try关键字后面的括号内.Java SE 7及更高版本中的BufferedReader类实现了java.lang.AutoCloseable接口.因为BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是正常还是突然完成,它都将被关闭

您可以从这里阅读更多内容.


And*_*nek 7

在Java中,如果使用输入或输出流等资源,则必须在使用后关闭它.它也可以抛出异常,因此必须处于try catch阻塞状态.关闭必须在finally块中.这是Java 7之前的最小方法.这有几个缺点:

  • 您必须null在关闭之前检查您的资源是否正确
  • 结束本身可以抛出异常,所以你finally必须包含另一个try-catch
  • 程序员往往忘记关闭他们的资源

虽然前两个主要是语法问题,但最后一个更为关键.因此,如果您使用try-with语句,您的代码会变得更加清晰,最重要的是:您的资源将始终关闭:-)


Ani*_*kur 6

优点是您无需显式关闭在try-with-resources语句中定义的资源.JVM将负责它.它会自动为您关闭这些资源.

开发人员面临的问题通常是构造try-catch-finally块,因为即使在我们关闭资源的finally块中,我们也必须使用try-catch.有各种try-catch-finally语句结构可以帮助解决这个问题但是try-with-resources语句基本上可以帮助您简化编码结构逻辑.


rak*_*aht 5

Java 9发行后的2017年更新

现在Java 9有了更多的语法糖,我们可以在try-catch块外声明资源,但仍然可以正确处理。

让我们以这种Java 6处理资源的方式为例:

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里我们可以注意到,正如其他答案中指出的那样,此代码非常丑陋。

因此,解决方案Java 7是引入以下内容try-catch-with-resource

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}
Run Code Online (Sandbox Code Playgroud)

这个表示法肯定比以前的表示法好,但是我们有一个问题。如果资源(在这种情况下为strem)先前已经声明过,但是我们要确保在此块中正确处理了资源,则需要这样的技巧:

InputStream stream = new MyInputStream(...)
try (InputStream stream2 = stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}
Run Code Online (Sandbox Code Playgroud)

我们可以注意到,这种情况只能用另一段丑陋的代码来解决。这就是使用Java 9改进了Try-With-Resources并引入了新语法的原因:

InputStream stream = new MyInputStream(...)
try (stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}
Run Code Online (Sandbox Code Playgroud)

请注意,此语法将导致Java版本8或次要版本出现编译时错误

即使在大多数用例中,我们不需要try块范围之外的资源,这也是一种“自然”的编写方式。 唯一的限制是reader变量应该有效地是final或just final。