【发布时间】:2013-07-18 08:12:34
【问题描述】:
Java 7 有一个名为try-with-resources 的新特性。它是什么?为什么我们应该使用它,在哪里使用它,我们可以在哪里利用这个功能?
try 语句没有 catch 块,这让我很困惑。
【问题讨论】:
标签: java java-7 try-with-resources
Java 7 有一个名为try-with-resources 的新特性。它是什么?为什么我们应该使用它,在哪里使用它,我们可以在哪里利用这个功能?
try 语句没有 catch 块,这让我很困惑。
【问题讨论】:
标签: java java-7 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());
}
【讨论】:
使用 try-with-resources 的好处:
代码更易读,更易编写。
自动资源管理。
代码行数减少。
不需要finally阻塞来关闭资源。
我们可以在try-with-resources语句中打开多个资源,用分号隔开。例如,我们可以编写以下代码。
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
}
}
当在 try-with-resources 中打开多个资源时,它会以相反的顺序关闭它们以避免任何依赖问题。你可以扩展我的资源程序来证明这一点。
【讨论】:
现在有了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 中的解决方案是引入这个try-catch-with-resource:
try (InputStream stream = new MyInputStream(...)){
// ... use stream
} catch(IOException e) {
// handle exception
}
这个符号肯定比前一个要好得多,但是我们有一个问题。如果资源(在这种情况下为 stream)之前已经声明过,但我们想确保它在这个块中被正确处理,我们需要这样的技巧:
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 或次要版本的编译时错误
这是一种更“自然”的编写方式,即使在大多数用例中我们不需要 try 块范围之外的资源。 唯一的限制是 reader 变量应该是有效的 final 或只是 final。
【讨论】:
它是因为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-with-resources 你可以这样做:
try (InputStream stream = new MyInputStream(...)){
// ... use stream
} catch(IOException e) {
// handle exception
}
并且 close() 会被自动调用,如果它抛出一个 IOException ,它将被抑制(在Java Language Specification 14.20.3 中指定)。 java.sql.Connection
也是如此【讨论】:
if it throws an IOException, it will be handled in the same catch clause 这是误导。如果close() 抛出异常,则会被抑制。
stream 声明为final 并且您不需要检查if(stream != null)(它总是正确的)
作为stated in the documentation:
try-with-resources 语句是一个 try 语句,它声明一个 或更多资源。资源是必须在之后关闭的对象 该程序已完成。 try-with-resources 语句 确保每个资源在语句结束时关闭。任何 实现
java.lang.AutoCloseable的对象,其中包括所有 实现java.io.Closeable的对象可以用作 资源。以下示例从文件中读取第一行。它使用一个 BufferedReader 实例从文件中读取数据。缓冲阅读器 是程序完成后必须关闭的资源 它:
static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } }在本例中,try-with-resources 中声明的资源 语句是一个 BufferedReader。声明声明出现 在 try 关键字之后的括号内。班上 BufferedReader,在 Java SE 7 及更高版本中,实现了接口 java.lang.AutoCloseable。因为 BufferedReader 实例是 在 try-with-resource 语句中声明,它将被关闭 不管try语句是正常完成还是突然完成
您可以从here阅读更多内容。
【讨论】:
优点是你不需要显式关闭你在 try-with-resources 语句中定义的资源。 JVM 会处理它。它会自动为您关闭这些资源。
通常开发人员面临的问题是构建 try-catch-finally 块,因为即使在 finally 块中我们关闭资源的地方我们也必须使用 try-catch。 try-catch-finally 语句有多种结构可以帮助解决这个问题,但是 try-with-resources 语句基本上可以帮助您简化编码结构逻辑。
【讨论】:
在 Java 中,如果您使用诸如输入或输出流之类的资源,您总是必须在使用后关闭它。它还可以抛出异常,因此它必须位于 try catch 块中。关闭必须在finally 块中。这至少是 Java 7 之前的方式。这有几个缺点:
null
finally 必须包含另一个 try - catch
虽然前两个主要是语法问题,但最后一个更为关键。因此,如果您使用 try-with 语句,您的代码会变得更简洁,最重要的是:您的资源将始终关闭 :-)
【讨论】: