嵌套资源获取是否需要在Java中进行特殊处理?

Ale*_*nco 9 java nested exception

首先,是的,try-with-resource修复了这些问题中的任何一个......但是如果没有它,我无法看到它是如何工作的.

让我们以java文档中的代码为例,可以在这里找到 :

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果资源br.close()被获取,则会释放该资源.然而,

  • 如果new FileReader(path)成功然后new BufferedReader(...)抛出异常会发生什么?
  • java如何保证FileReader关闭?
  • 是否可以保证BufferedReader在已经打开的情况下创建FileReader将永远成功?如果是这样,为什么该方法被声明为抛出IOException

或者我们应该写下面的内容以确保情况不会发生?

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {

    FileReader fr;

    try {
        FileReader fr = new FileReader(path);
        BufferedReader br;
        try {
            BufferedReader br = new BufferedReader(fr);
            return br.readLine();
        } finally {
            if (br != null) br.close();
        }
    finally {
        // Implements closeable, so it is ok if we call it twice.
        if (fr != null) fr.close();
    }
}


Run Code Online (Sandbox Code Playgroud)

当然,使用try-with-resources,这个嵌套的混乱仍然消失,因为我们可以在同一个语句中声明多个资源.但我总是认为自己在尝试使用资源作为一种避免完全考虑这种情况的方法,并试图在网上找到一个我真的无法解决的问题.

任何帮助将不胜感激,谢谢!

Tom*_*ine 1

这些教程通常已经过时或者没有描述好的实践。

如果我们看看你引用的第一段代码,br永远不可能null。可以将其if ( )移除。这可能是由于以前的代码finallycatch. 如果一个try声明同时具有finally和 a ,catch那么它可能是错误的,并且几乎肯定会做一些不明智的事情。通常,您会看到null正在进行的舞蹈和至少一个明显的错误。

关于这个问题的普遍看法是,BufferedReader只有当整个过程出现严重错误时,这种方法才会失败。可能是内存不足或堆栈溢出。如果你遇到这类例外情况,你可能想完全摆脱这种情况。

不使用 try-with-resource 编写代码的迂腐方式是:

FileReader fr = new FileReader(path);
try {
    BufferedReader br = new BufferedReader(fr);
    return br.readLine();
} finally {
    fr.close();
}
Run Code Online (Sandbox Code Playgroud)

然而,在某些情况下,您可能会犯错。经过考虑的BufferWriter。你已经忘记了flush,不是吗?我的意思是,我会的。如果你把它关闭在 a 中finally,那就不会有问题了。还有一些装饰器本身就是资源。例如,它们可能有一个使用非垃圾收集内存的本机实现。这不一定有记录。

关闭资源和装饰器并不困难,但在不尝试使用资源的情况下确实有点向右转。

// (Using same example even though it doesn't matter here - imaging a Writer)
FileReader fr = new FileReader(path);
try {
    BufferedReader br = new BufferedReader(fr);
    try {
        return br.readLine();
    } finally {
        br.close();
    }
} finally {
    fr.close();
}
Run Code Online (Sandbox Code Playgroud)