88

如果抛出异常,我期望缓冲读取器和文件读取器关闭并释放资源。

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

2 回答 2

105

这是正确的,没有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.

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

编辑

关于新编辑的问题:

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

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

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

于 2013-07-15T09:40:04.470 回答
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);
    } 
}

假设出了什么问题,你最终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仍然会关闭。您可以在此处此处找到更多详细信息。

于 2014-01-25T09:37:02.290 回答