是否有一种优雅的方法来处理finally
块中抛出的异常?
例如:
try { // Use the resource. } catch( Exception ex ) { // Problem with the resource. } finally { try{ resource.close(); } catch( Exception ex ) { // Could not close the resource? } }
你如何避免try
/ catch
在finally
街区?
我通常这样做:
try { // Use the resource. } catch( Exception ex ) { // Problem with the resource. } finally { // Put away the resource. closeQuietly( resource ); }
别处:
protected void closeQuietly( Resource resource ) { try { if (resource != null) { resource.close(); } } catch( Exception ex ) { log( "Exception during Resource.close()", ex ); } }
我通常使用以下closeQuietly
方法之一org.apache.commons.io.IOUtils
:
public static void closeQuietly(OutputStream output) { try { if (output != null) { output.close(); } } catch (IOException ioe) { // ignore } }
如果你正在使用Java 7和resource
implements AutoClosable
,你可以这样做(使用InputStream作为例子):
try (InputStream resource = getInputStream()) { // Use the resource. } catch( Exception ex ) { // Problem with the resource. }
可以说有点超过顶部,但是如果你让异常冒出来并且你不能在你的方法中记录任何东西(例如因为它是一个库而你宁愿让调用代码处理异常和日志记录)也许有用:
Resource resource = null; boolean isSuccess = false; try { resource = Resource.create(); resource.use(); // Following line will only run if nothing above threw an exception. isSuccess = true; } finally { if (resource != null) { if (isSuccess) { // let close throw the exception so it isn't swallowed. resource.close(); } else { try { resource.close(); } catch (ResourceException ignore) { // Just swallow this one because you don't want it // to replace the one that came first (thrown above). } } } }
更新:我看着这更多了一下,发现从别人一个伟大的博客文章谁显然已经想过这个比我:http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html 他更进了一步,将两个例外合并为一个,我认为在某些情况下它是有用的.
从Java 7开始,您不再需要显式关闭finally块中的资源,而是可以使用try -with-resources语法.try-with-resources语句是一个声明一个或多个资源的try语句.资源是在程序完成后必须关闭的对象.try-with-resources语句确保在语句结束时关闭每个资源.实现java.lang.AutoCloseable的任何对象(包括实现java.io.Closeable的所有对象)都可以用作资源.
假设以下代码:
try( Connection con = null; Statement stmt = con.createStatement(); Result rs= stmt.executeQuery(QUERY);) { count = rs.getInt(1); }
如果发生任何异常,将按照创建它们的相反顺序在这三个资源中的每一个上调用close方法.这意味着将首先为ResultSetm调用close方法,然后调用Statement,最后调用Connection对象.
同样重要的是要知道自动调用close方法时发生的任何异常都会被抑制.可以通过Throwable类中定义的getsuppressed()方法检索这些抑制的异常.
资料来源:https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html