我是否正确使用Java 7 try-with-resources

Che*_*tah 86 java-7 try-with-resources

我期待缓存的读取器和文件读取器关闭,如果异常抛出则释放资源.

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

但是,是否需要有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;
}
Run Code Online (Sandbox Code Playgroud)

yai*_*air 102

这是正确的,没有catch条款要求.Oracle java 7 doc说,无论是否实际抛出异常,资源都将被关闭.

catch只有在想要对异常作出反应时才应使用子句.该资源catch将在资源关闭执行.

以下是Oracle教程的片段:

以下示例从文件中读取第一行.它使用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.
Run Code Online (Sandbox Code Playgroud)

...因为BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是正常完成还是突然完成(由于BufferedReader.readLine方法抛出IOException),它都将被关闭.

编辑

关于新编辑的问题:

Java 6中的代码执行块catch之后finally.这导致资源仍然可能在catch块中打开.

在Java 7语法中,资源在块之前关闭catch,因此在catch块执行期间资源已经关闭.这在以上链接中记录:

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


And*_*nin 69

您对try-with-resources的使用在这种特殊情况下可以正常工作,但一般情况下它并不完全正确.你不应该链接这样的资源,因为它可能会导致令人不快的意外.假设您有一个可变缓冲区大小:

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);
    } 
}
Run Code Online (Sandbox Code Playgroud)

假设出了问题,最后你就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);
    } 
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,即使br失败的初始化file仍然关闭.您可以在此处此处找到更多详细信息.

  • @jschreiner是的,尽管Andrii(有点人为的)问题,其中`sz <0`导致构造函数抛出异常,实际上会导致资源泄漏. (7认同)
  • @mario我同意.外部构造函数可能会失败,内部资源将被泄露.我之前没有看到,谢谢. (5认同)
  • Andrii和@Mario你是对是错.在第一个示例中,try-with-resource逻辑未关闭FileReader.但是当BufferedReader关闭时,它也将关闭包装的FileReader.有关证明,请查看java.io.BufferedReader.close()的源代码.因此,应优先考虑第一个示例中的代码,因为它更简洁. (4认同)
  • @PrasoonJoshi不,它只调用`.close()`来表示在try-with-resources初始值设定项中声明的变量.这就是为什么在这个例子中将它分成两个声明的原因. (3认同)