我是否正确使用了Java 7的try-with-resources
我期待缓冲的阅读器和文件阅读器closures,并释放资源,如果抛出exception。
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException { try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { return read(br); } }
但是,是否有要求成功closures的catch
条款?
编辑:
从本质上讲,Java 7中的上述代码等同于下面的Java 6:
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException { BufferedReader br = null; try { br = new BufferedReader(new FileReader(filePath)); return read(br); } catch (Exception ex) { throw ex; } finally { try { if (br != null) br.close(); } catch(Exception ex) { } } return null; }
这是正确的,并没有要求catch
语句。 Oracle java 7 doc表示, 无论是否实际抛出exception,资源都将被closures。
只有当你想对exception作出反应时,你才应该使用catch
子句。 catch
子句将在资源closures后执行。
以下是Oracle教程的一个片段:
以下示例从文件读取第一行。 它使用BufferedReader的实例从文件中读取数据。 BufferedReader是程序完成后必须closures的资源:
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.
…因为BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是正常还是突然完成(由于BufferedReader.readLine抛出一个IOException),它都将被closures。
编辑
关于新编辑的问题:
Java 6中的代码执行catch
和之后的finally
块。 这导致资源仍然可能在catch
块中打开。
在Java 7语法中,资源在catch
块之前closures,因此资源在catch
块执行期间已经closures。 这在上面的链接中有logging:
在try-with-resources语句中,声明的资源closures后,将运行任何catch或finally块。
在这种特殊情况下,您对资源尝试的使用可以很好地工作,但总的来说这是不正确的。 你不应该像这样链接资源,因为它可能会导致不愉快的意外。 假设你有一个可变的缓冲区大小:
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException { int sz = /* get buffer size somehow */ try (BufferedReader br = new BufferedReader(new FileReader(filePath), sz)) { return read(br); } }
假设出了问题,你最终以sz
为负。 在这种情况下,您的文件资源(通过new FileReader(filePath)
创build) 不会被closures。
为了避免这个问题,你应该像这样分别指定每个资源:
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException { int sz = /* get buffer size somehow */ try (FileReader file = new FileReader(filePath); BufferedReader br = new BufferedReader(file, sz)) { return read(br); } }
在这种情况下,即使初始化失败file
仍然closures。 你可以在这里和这里find更多的细节。