为什么我会收到带有包装编写器对象的"potential resource leak"警告?



我让Eclipse发出以下警告:

Potential resource leak: '<unassigned Closeable value>' may not be closed

对于以下代码段中的表达式new BufferedWriter(...)

boolean useStdout = askUserWhetherToUseStdout();
Writer writer = useStdout ? new OutputStreamWriter(System.out) : new BufferedWriter(new FileWriter(new File(askUserForFilename())));
try {
    writer.write("Hello World!");
}
finally {
    writer.close();
}

这是假阳性吗?我理解整个Writer的方式是,任何作家都会关闭其底层作家。在我的情况下,writer将封装新的缓冲写入程序(进而封装文件写入程序(,因此关闭writer不应该泄露与缓冲写入程序或其底层写入程序相关的任何资源?

我在这里错过了什么?

根据更新的问题编辑的答案:

这是一个基于三元运算符使用的虚假警告。如果操作的右侧没有激发,则不会创建BufferedWriter,也不会出现资源泄漏。因此,警告所描述的事实上是不可能的。然而,如果你想"处理"它,只需将编写器的创建移动到你的try块中即可。

boolean useStdout = askUserWhetherToUseStdout();
Writer writer = null;
try {
    writer = useStdout ? new OutputStreamWriter(System.out)
            : new BufferedWriter(new FileWriter(new File(
                    askUserForFilename())));
    writer.write("Hello World!");
} finally {
    if (writer != null)
        writer.close();
}

如果writer.write("Hello World!");抛出异常,则永远不会调用writer.close()

尝试将其包装到Try-catch块中(可能利用了自动关闭功能,请参阅http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)。

你能检查一下这个代码是否给你警告吗?若并没有,那个么在创建编写器时可能并没有处理IOException,这也应该在try块中完成。

boolean useStdout = askUserWhetherToUseStdout();
Writer writer = null;
try {
    writer = useStdout ? new OutputStreamWriter(System.out)
            : new BufferedWriter(new FileWriter(new File(
                    askUserForFilename())));
    writer.write("Hello World!");
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (writer != null)
            writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

您也可以使用带有资源的try,它将在try块后自动关闭资源流。

boolean useStdout = askUserWhetherToUseStdout();
try (Writer writer = useStdout ? new OutputStreamWriter(System.out)
        : new BufferedWriter(new FileWriter(new File(
                askUserForFilename())))) {
    writer.write("Hello World!");
} catch (IOException e) {
    e.printStackTrace();
}

最新更新