[英]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 implementjava.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 语句是正常完成还是突然完成,它都会被关闭
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 之前的方式。 这有几个缺点:
null
before closing itnull
finally
had to contain another try
- catch
finally
必须包含另一个try
- catch
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 的好处:
More readable code and easy to write.更易读的代码和易于编写。
Automatic resource management.自动资源管理。
Number of lines of code is reduced.代码行数减少。
No need of finally block just to close the resources.不需要 finally 块只是为了关闭资源。
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 } }
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.