简体   繁体   English

try-with-resources 语句的目的是什么?

[英]What's the purpose of try-with-resources statements?

Java 7 has a new feature called try-with-resources . Java 7 有一个名为try-with-resources的新功能。 What is it?它是什么? Why and where we should use it and where we can take advantage of this feature?为什么我们应该使用它,在哪里使用它,我们可以在哪里利用这个特性?

The try statement has no catch block which confuses me. try语句没有让我感到困惑的catch块。

It was introduced because of some resources used in Java (like SQL connections or streams) being difficult to be handled properly;引入它是因为 Java 中使用的某些资源(如 SQL 连接或流)难以正确处理; as an example, in java 6 to handle a InputStream properly you had to do something like:例如,在 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
    }
}

Do you notice that ugly double try?你注意到丑陋的双重尝试了吗? now with try-with-resources you can do this:现在使用 try-with-resources 你可以这样做:

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

and close() is automatically called, if it throws an IOException, it will be supressed (as specified in the Java Language Specification 14.20.3 ) .并且close()被自动调用,如果它抛出一个 IOException,它将被抑制(如Java 语言规范 14.20.3 中所述)。 Same happens for java.sql.Connection java.sql.Connection 也是如此

As stated in the documentation :文档中所述

The try-with-resources statement is a try statement that declares one or more resources. try-with-resources 语句是一种声明一个或多个资源的 try 语句。 A resource is an object that must be closed after the program is finished with it.资源是程序完成后必须关闭的对象。 The try-with-resources statement ensures that each resource is closed at the end of the statement. try-with-resources 语句确保每个资源在语句结束时关闭。 Any object that implements java.lang.AutoCloseable , which includes all objects which implement java.io.Closeable , can be used as a resource.任何实现java.lang.AutoCloseable对象,包括实现java.io.Closeable所有对象,都可以用作资源。

The following example reads the first line from a file.以下示例从文件中读取第一行。 It uses an instance of BufferedReader to read data from the file.它使用 BufferedReader 的一个实例从文件中读取数据。 BufferedReader is a resource that must be closed after the program is finished with it: BufferedReader 是程序完成后必须关闭的资源:

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

In this example, the resource declared in the try-with-resources statement is a BufferedReader.在这个例子中,在 try-with-resources 语句中声明的资源是一个 BufferedReader。 The declaration statement appears within parentheses immediately after the try keyword.声明语句紧跟在 try 关键字之后的括号内。 The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Java SE 7 及更高版本中的 BufferedReader 类实现了接口 java.lang.AutoCloseable。 Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly因为 BufferedReader 实例是在 try-with-resource 语句中声明的,所以无论 try 语句是正常完成还是突然完成,它都会被关闭

You can read more from here .您可以从这里阅读更多内容。

Update from 2017 after Java 9 release Java 9 发布后从 2017 年开始的更新

Now with Java 9 we have more syntactic sugar and we can have a resource declared outside the try-catch block but still handled properly.现在有了Java 9我们有了更多的语法糖,我们可以在try-catch块之外声明一个资源,但仍然可以正确处理。

Let's take for example this Java 6 way of handling the resource:让我们以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
    }
}

Here we can notice that this code is incredibly ugly as pointed out in other answers.在这里我们可以注意到,正如其他答案中指出的那样,这段代码非常难看。

So the solution in Java 7 was to introduce this try-catch-with-resource :所以Java 7的解决方案是引入这个try-catch-with-resource

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

This notation is surely way better than the previous one, however we have a problem.这种表示法肯定比前一种好得多,但是我们有一个问题。 If the resource ( stream in this case) has been declared previously but we want to be sure that it's handled correctly in this block we need a trick like this:如果之前已经声明了资源(在这种情况下是),但我们想确保它在这个块中得到正确处理,我们需要一个像这样的技巧:

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
}

We can notice that this situation can be addressed only with another piece of ugly code.我们可以注意到,这种情况只能通过另一段丑陋的代码来解决。 That's why with Java 9 the Try-With-Resources has been improved introducing a new syntax:这就是为什么在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
}

Note that this syntax will result in a compile time error for Java version 8 or minor请注意,此语法将导致 Java 8 或次要版本的编译时错误

This is more "natural" way of writing even though in most use cases we don't need the resource outside the scope of the try block.这是更“自然”的编写方式,即使在大多数用例中我们不需要 try 块范围之外的资源。 The only restriction is that the reader variable should be effectively final or just final.唯一的限制是 reader 变量应该是有效的 final 或只是 final。

In Java, if you use a resource like input or output streams you always have to close it after using.在 Java 中,如果您使用诸如输入或输出流之类的资源,则在使用后始终必须关闭它。 It also can throw exceptions so it has to be in a try catch block.它也可以抛出异常,所以它必须在try catch块中。 The closing has to be in the finally block.结束必须在finally块中。 This is a least the way until Java 7. This has several disadvantages:这至少是 Java 7 之前的方式。 这有几个缺点:

  • You'd have to check if your ressource is null before closing it您必须在关闭之前检查您的资源是否为null
  • The closing itself can throw exceptions so your finally had to contain another try - catch关闭本身可能会引发异常,因此您finally必须包含另一个try - catch
  • Programmers tend to forget to close their ressources程序员往往忘记关闭他们的资源

While the first two are mostly syntax issues, the last one is more critical.虽然前两个主要是语法问题,但最后一个更为关键。 So if you use the try-with statement your code gets a lot cleaner and most importantly: Your ressource will always be closed :-)因此,如果您使用 try-with 语句,您的代码将变得更加清晰,最重要的是:您的资源将始终关闭:-)

The advantage is you need not explicitly close the resources you have defined in try-with-resources Statement.优点是您不需要明确关闭在 try-with-resources 语句中定义的资源。 JVM will take care of it. JVM 会处理它。 It will automatically close those resources for you.它会自动为您关闭这些资源。

Generally problems developers face is to structure the try-catch-finally blocks because even in finally block where we close the resources we have to use try-catch.通常,开发人员面临的问题是构建 try-catch-finally 块,因为即使在 finally 块中我们关闭资源,我们也必须使用 try-catch。 There are various structures of try-catch-finally statement to help resolve this issue but try-with-resources Statement will basically help you ease your coding structure logic.有多种结构的 try-catch-finally 语句可以帮助解决此问题,但 try-with-resources 语句基本上可以帮助您简化编码结构逻辑。

Benefits of using try-with-resources:使用 try-with-resources 的好处:

  1. More readable code and easy to write.更易读的代码和易于编写。

  2. Automatic resource management.自动资源管理。

  3. Number of lines of code is reduced.代码行数减少。

  4. No need of finally block just to close the resources.不需要 finally 块只是为了关闭资源。

  5. We can open multiple resources in try-with-resources statement separated by a semicolon.我们可以在 try-with-resources 语句中打开多个资源,以分号分隔。 For example, we can write following code.例如,我们可以编写以下代码。

     public void sampleTryWithResource() { try(Connection dbCon = DriverManager.getConnection("url", "user", "password"); BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));) { //...Your Business logic } catch (Exception e) { //...Exception Handling } }
  6. When multiple resources are opened in try-with-resources, it closes them in the reverse order to avoid any dependency issue.当在 try-with-resources 中打开多个资源时,它会以相反的顺序关闭它们以避免任何依赖性问题。 You can extend my resource program to prove that.你可以扩展我的资源程序来证明这一点。

You can try this - if resource is initialized inside try{} it is automatically closed:你可以试试这个 - 如果资源在 try{} 中初始化,它会自动关闭:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM