Java 什么';try with resources语句的目的是什么?
Java7有一个新特性,叫做。这是怎么一回事?我们为什么要使用它,应该在哪里使用它,我们可以在哪里利用这个特性Java 什么';try with resources语句的目的是什么?,java,java-7,try-with-resources,Java,Java 7,Try With Resources,Java7有一个新特性,叫做。这是怎么一回事?我们为什么要使用它,应该在哪里使用它,我们可以在哪里利用这个特性 try语句没有使我困惑的catch块。如下: try with resources语句是一个try语句,它声明了一个 或者更多的资源。资源是一个对象,必须在 程序结束了。try with resources语句 确保在语句末尾关闭每个资源。任何 实现java.lang.AutoCloseable,其中包括所有 实现java.io.Closeable的对象可以用作 资源 下面的示例从文件
try
语句没有使我困惑的catch
块。如下:
try with resources语句是一个try语句,它声明了一个
或者更多的资源。资源是一个对象,必须在
程序结束了。try with resources语句
确保在语句末尾关闭每个资源。任何
实现java.lang.AutoCloseable
,其中包括所有
实现java.io.Closeable
的对象可以用作
资源
下面的示例从文件中读取第一行。它使用一个
从文件中读取数据的BufferedReader实例。缓冲区读取
是必须在程序结束后关闭的资源
它:
在本例中,在try with resources中声明的资源
语句是一个BufferedReader。此时将显示声明语句
在try关键字后面的括号内。班级
BufferedReader在JavaSE7及更高版本中实现了该接口
java.lang.AutoCloseable。因为BufferedReader实例是
在try with resource语句中声明,它将被关闭
不管try语句是正常完成还是突然完成
您可以从中阅读更多内容。之所以引入它,是因为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
}
}
你注意到那个丑陋的双重尝试了吗?现在,使用“试用资源”,您可以执行以下操作:
try (InputStream stream = new MyInputStream(...)){
// ... use stream
} catch(IOException e) {
// handle exception
}
并自动调用close(),如果它抛出IOException,它将被抑制(如中所指定)。java中的java.sql.Connection也会发生同样的情况,如果您使用输入流或输出流之类的资源,那么在使用后总是必须关闭它。它还可以抛出异常,因此它必须位于
try
catch
块中。关闭必须在finally
块中。在Java7之前,这是一种最起码的方法。这有几个缺点:
- 在关闭ressource之前,您必须检查它是否为
null
- 关闭本身可能引发异常,因此您的
必须包含另一个最终
-try
catch
- 程序员往往忘记关闭他们的资源
前两个主要是语法问题,后一个更为关键。因此,如果您使用try-with语句,您的代码将变得更干净,而且最重要的是:您的ressource将始终关闭:-)优点是您不需要显式关闭try-with-resources语句中定义的资源。JVM会处理它。它将自动为您关闭这些资源
开发人员通常面临的问题是构造try-catch-finally块,因为即使在finally块中关闭资源,我们也必须使用try-catch。try-catch-finally语句有多种结构可以帮助解决此问题,但try-with-resources语句基本上可以帮助您简化编码结构逻辑。您可以尝试此方法-如果资源在try{}内初始化,它将自动关闭:
try {
Scanner scanner = new Scanner(new File(csvFile));
while (scanner.hasNext()) {
// do something
}
scanner.close();
}catch(FileNotFoundException fnfe)
{
System.err.println(fnfe.getLocalizedMessage());
}
使用“与资源一起尝试”的好处:
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
}
}
java9
我们有了更多的语法糖,我们可以在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
}
}
在这里,我们可以注意到,正如其他答案所指出的,这个代码非常丑陋
因此Java7
中的解决方案是引入这个try catch with resource
:
try (InputStream stream = new MyInputStream(...)){
// ... use stream
} catch(IOException e) {
// handle exception
}
这个符号肯定比前一个好得多,但是我们有一个问题。如果资源(在本例中为流)先前已声明,但我们希望确保在该块中正确处理,则需要以下技巧:
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改进了“资源试用”引入了一种新语法:
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或更小版本,此语法将导致编译时错误
这是一种更“自然”的编写方式,即使在大多数用例中,我们不需要try块范围之外的资源。
唯一的限制是reader变量应该是有效的final或刚好final。看看trailIf如果BufferedReader构造函数抛出异常(不太可能),FileReader将不会关闭。Personnaly我发现try with resources语句也非常难看。当您有多个资源时,情况更糟。@morgano如果它抛出IOException,它将在同一catch子句中处理,这是误导。如果close()
抛出异常,它将被抑制。将stream
声明为final
,并且不需要检查是否(stream!=null)
(它将始终为真)
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
}