2013-07-15 30 views
61

我在期待缓冲的阅读器和文件阅读器关闭,并在抛出异常时释放资源。我是否正确使用Java 7试用资源

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 
    try (BufferedReader br = new BufferedReader(new FileReader(filePath))) 
    { 
     return read(br); 
    } 
} 

但是,是否有要求成功关闭的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; 
} 
+0

再次阅读您的问题后,我不确定我是否理解得很好。你能解释一下吗? – Maroun

+0

嗨。猎豹,我试图理解你的Java 6第一个catch的作用。 catch(Exception ex){throw ex; }' - 它只是重新抛出异常,它什么都不做,它可以轻松移除而不会受到任何伤害。或者我错过了什么? – Sasha

+0

你的语法没有错。如果你想了解更多关于试用资源的知识,请查看这篇文章:[Java试用资源](http://programmergate.com/java-try-resources/) –

回答

84

这是正确的,并有一个为catch子句没有要求。 Oracle java 7 doc说资源将被关闭不管是否实际抛出异常。

只有当您想对异常做出反应时,才应该使用catch子句。在资源关闭后,将执行catch子句

这里有一个片段从Oracle's tutorial

下面的示例读取从文件的第一行。它使用BufferedReader的一个实例来读取文件中的数据。 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. 

...因为的BufferedReader实例在 试穿与资源声明中宣布,它会被关闭,无论 try语句是否正常或突然完成(由于 方法BufferedReader.readLine抛出IOException)。

EDIT

关于新编辑的问题:

Java 6中的代码执行和catch事后finally块。这会导致资源仍可能在catch块中打开。

在Java 7语法中,之前的资源是之前的catch块,所以资源在catch块执行期间已经关闭。这在上面的链接中有记录:

在try-with-resources语句中,在声明的资源关闭后,任何catch或finally块都会运行 。

58

在这种特殊情况下,您对资源尝试的使用可以正常工作,但通常情况下它并不完全正确。你不应该像这样链接资源,因为它可能会导致不愉快的意外。假设你有一个变量的缓冲区大小:

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)创建)将会关闭而不是

为了避免这个问题,您应该分别指定每个资源是这样的:

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); 
    } 
} 

在这种情况下,即使br初始化仍然失败file被关闭。你可以找到更多的细节herehere

+0

我试图理解为什么通过'FileReader(filePath)'创建的资源''在sz为负时抛出'IllegalArgumentException'的情况下不会关闭。不管任何抛出的异常,try-with-resources不会关闭所有'AutoClosable'资源吗? –

+2

@PrasoonJoshi不,它只为'try-with-resources'初始化程序中声明的变量调用'.close()'。这就是为什么在这个例子中将它分成两个声明的原因。 –

+3

Andrii和@Mario你是对的也是错的。在第一个例子中,FileReader没有被try-with-resource逻辑关闭。但是,当BufferedReader关闭时,它也会关闭包装的FileReader。为了证明,看看java.io.BufferedReader.close()的来源。因此,应优先考虑来自第一个示例的代码,因为它更简洁。 – jschreiner