Java7试用资源声明的优势

我正在看Java7的新function。 我发现一个是试用资源的声明 。 谁能告诉我究竟是什么意思? 为什么和在哪里我们应该使用它,在哪里我们可以得到这个function的优势? 甚至try声明错过了为我迷惑的块。

它是由于Java中使用的一些资源(如SQL连接或stream)难以正确处理而引入的; 作为一个例子,在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 } } 

你注意到丑陋的双重尝试? 现在尝试与资源,你可以做到这一点:

 try (InputStream stream = new MyInputStream(...)){ // ... use stream } catch(IOException e) { // handle exception } 

close()会自动调用,如果抛出一个IOException,它将被压制(如Java语言规范14.20.3中所指定的)。 java.sql.Connection也是如此

正如文件中所述 :

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

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

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

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

你可以从这里阅读更多。

在Java中,如果使用input或输出stream等资源,则在使用后必须closures它。 它也可以抛出exception,所以它必须在try catch块中。 closures必须在finally块。 这是Java 7之前的最低速度。这有几个缺点:

  • 在closures它之前,你必须检查你的资源是否为null
  • closures本身可以抛出exception,所以你finally不得不包含另一个trycatch
  • 程序员往往忘记closures他们的资源

虽然前两个主要是语法问题,但最后一个更重要。 所以,如果你使用try-with语句,你的代码会变得更清洁,最重要的是:你的资源将永远被closures:-)

好处是您不需要明确地closures您在try-with-resources Statement中定义的资源。 JVM会照顾它。 它会自动为你closures这些资源。

一般来说,开发人员面临的问题是构buildtry-catch-finally块,因为即使在最后closures资源的地方,我们也必须使用try-catch。 try-catch-finally语句有各种结构来帮助解决这个问题,但是试用资源语句基本上可以帮助您减轻编码结构的逻辑。

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 } } 

在这里我们可以注意到,这个代码在其他答案中指出是非常难看的。

所以Java 7的解决scheme是引入这个try-catch-with-resource

 try (InputStream stream = new MyInputStream(...)){ // ... use stream } catch(IOException e) { // handle exception } 

这个符号肯定比前一个更好,但是我们有一个问题。 如果资源(本例中是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 } 

我们可以注意到,这种情况只能用另一个丑陋的代码来解决。 这就是为什么在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 } 

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

这是更“自然”的写作方式,尽pipe在大多数情况下,我们不需要超出try块范围的资源。 唯一的限制是读者variables应该是有效的或者只是最终的。

使用资源尝试的好处

  1. 更易读的代码,易于编写。

  2. 自动资源pipe理。

  3. 代码行数减less。

  4. 没有必要最后阻止只是closures资源。

  5. 我们可以在以分号分隔的try-with-resources语句中打开多个资源。 例如,我们可以写下面的代码。

  6. 当在资源尝试中打开多个资源时,它将以相反的顺序closures它们以避免任何依赖性问题。 你可以扩展我的资源程序来certificate这一点。

那么怎么样 – 如果资源在try {}中初始化,它会自动closures吗?

 try { Scanner scanner = new Scanner(new File(csvFile)); while (scanner.hasNext()) { // do something } scanner.close(); }catch(FileNotFoundException fnfe) { System.err.println(fnfe.getLocalizedMessage()); }