为什么要编写没有Catch或Finally的Try-With-Resources?

70

为什么在以下示例中不使用Catch或Finally来写Try?

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=UTF-8");
    try (PrintWriter out = response.getWriter()) {
        /* TODO output your page here. You may use following sample code. */
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet tryse</title>");            
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Servlet tryse at " + request.getContextPath() + "</h1>");
        out.println("</body>");
        out.println("</html>");
    }

}

8
阅读有关Java 7中使用"try with resources"的内容。 - Eran
9
请参阅使用try-with-resources语句 - Justin
“try-finally”不带“catch”是否有意义的副本? - Juru
8
@Juru:这绝不是那个的复制品... - Oliver Charlesworth
1
话虽如此,我不认为这是关于try-with-resources的第一个问题。尽管如此,我还是点赞了,因为我以前从未听说过这个功能! - Oliver Charlesworth
显示剩余2条评论
2个回答

85

如上所述,这是Java 7及以上版本的一个特性。try with resources允许跳过编写finally并关闭在try-block中使用的所有资源。如文档中所述:

任何实现了java.lang.AutoCloseable接口的对象都可以用作资源,其中包括所有实现了java.io.Closeable接口的对象。

请参阅此代码示例。

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}
在这个示例中,资源是一个 BufferReader 对象,因为该类实现了接口 java.lang.AutoCloseable,即使 try 块没有成功执行,它也会被关闭,这意味着您不必显式地编写 br.close()
另一个需要注意的重要事情是,如果您自己编写了 finally 块,并且您的 try 块和 finally 块都抛出异常,则来自 try 块的异常将被压制。
另一方面,如果您使用 try-with-resources 语句并且 try 块和 try-with-resources 语句都抛出异常,则在这种情况下,try-with-resources 语句中的异常将被压制。
正如 @Aaron 已经在上面回答过的,我只是试图向您解释。希望能帮到您。
来源:http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

4
这句话的意思是:这类似于 C# 中使用 IDisposable 的情况。 - roufamatic
2
@roufamatic 是的,类似,但主要区别在于 C# 的 using 无法保护异常,它只能保证在块结束时关闭资源。在 C# 中,你通常需要将 using 块与 try 块结合使用。而 Java 的 try-with-resources 则将两者结合在一起。 - Michael Plautz
如果try-with-resources语句和try-with-resources块都抛出异常,则只会遇到(不会被抑制)try-with-resources语句异常,因为try-with-resources块没有执行的机会。 - dan

13

这是Java 7及以后版本中的新功能。如果没有它,你需要一个finally块来关闭资源PrintWriter out。因此,上面的代码等同于:

这是Java 7及以后版本中的新功能。如果没有它,你需要一个finally块来关闭资源PrintWriter out。因此,上面的代码等同于:

PrintWriter out = null;
try {
    PrintWriter out = ...
} finally {
    if(null != out) {
        try {
            out.close();
        } catch(Exception e) {} // silently ignore!
    }
}

请查看try-with-resources语句


2
它们并不相等。如果异常从try和finally块中抛出,使用try-catch将会抑制try块中的异常。另一方面,如果您使用try-with-resources语句,则会抑制finally块(自动关闭引发异常)中的异常。 - Nier
@Nier 修复了 finally 部分。 - Aaron Digulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接