使用try-with-resources静静地关闭资源
是否可以忽略使用try-with-resources语句关闭资源时抛出的exception?
例:
class MyResource implements AutoCloseable{ @Override public void close() throws Exception { throw new Exception("Could not close"); } public void read() throws Exception{ } } //this method prints an exception "Could not close" //I want to ignore it public static void test(){ try(MyResource r = new MyResource()){ r.read(); } catch (Exception e) { System.out.println("Exception: " + e.getMessage()); } }
或者我应该继续关闭?
public static void test2(){ MyResource r = null; try { r.read(); } finally{ if(r!=null){ try { r.close(); } catch (Exception ignore) { } } } }
我在coin-dev邮件列表中找到了这个答案: http : //mail.openjdk.java.net/pipermail/coin-dev/2009-April/001503.html
5.可以安全地忽略close方法的某些失败(例如,关闭打开以供读取的文件)。 构造是否提供了这个?
不会。虽然这个function似乎很有吸引力,但不清楚它是否值得增加复杂性。 实际上,这些“无害的exception”很少发生,所以如果忽略这些exception,程序就不会更加健壮。 如果您觉得必须忽略它们,那么有一种解决方法,但它并不漂亮:
static void copy(String src, String dest) throws IOException { boolean done = false; try (InputStream in = new FileInputStream(src)) { try(OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[8192]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } done = true; } catch(IOException e) { if (!done) throw e; } }
您可以在此处使用装饰器模式来安静地关闭资源:
public class QuietResource implements AutoCloseable{ T resource; public QuietResource(T resource){ this.resource = resource; } public T get(){ return resource; } @Override public void close() { try { resource.close(); }catch(Exception e){ // suppress exception } } }
我个人并不喜欢结果语法,但也许这适合你:
public static void test(){ try(QuietResource qr = new QuietResource<>(new MyResource())){ MyResource r = qr.get(); r.read(); } catch (Exception e) { System.out.println("Exception: " + e.getMessage()); } }
如果您愿意限制自己处理接口并利用动态代理类,则可以做得更好:
public class QuietResource implements InvocationHandler { private T resource; @SuppressWarnings("unchecked") public static V asQuiet(V resource){ return (V) Proxy.newProxyInstance( resource.getClass().getClassLoader(), resource.getClass().getInterfaces(), new QuietResource (resource)); } public QuietResource(T resource){ this.resource = resource; } @Override public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { if(m.getName().equals("close")){ try { return m.invoke(resource, args); }catch(Exception e){ System.out.println("Suppressed exception with message: " + e.getCause().getMessage()); // suppress exception return null; } } return m.invoke(resource, args); } }
然后假设你有:
public interface MyReader extends AutoCloseable{ int read(); }
使用实际资源类:
public class MyResource implements MyReader { public void close() throws Exception{ throw new Exception("ha!"); } public int read(){ return 0; } }
调用语法如下:
public static void test(){ try(MyReader r = QuietResource.asQuiet(new MyResource())){ r.read(); } catch (Exception e) { System.out.println("Exception: " + e.getMessage()); } }
如果要开始包含库(如AOP启用程序),则可以做得更好。 但是,这些解决方案将与JDK7一起开箱即用,没有其他依赖关系。
这是一个解决方案:
boolean ok=false; try(MyResource r = new MyResource()) { r.read(); ok=true; } catch (Exception e) { if(ok) ; // ignore else // e.printStackTrace(); throw e; }
如果ok==true
并且我们得到了一个exception,它肯定来自close()
。
如果ok==false
,则e
来自read()
或构造函数。 仍然会调用close()
并抛出e2
,但无论如何都会抑制e2。
代码非常易读,无需经过此类分析。 直观地说,如果ok==true
,我们的实际工作已经完成,我们并不关心资源之后的错误。
- 使用Jquery和servlet检索图像会产生HTTP状态500错误
- 读取Excel文档时出现问题(Java代码)
- 将已检查的exception包装到Java中未经检查的exception中?
- java.lang.ArrayIndexOutOfBoundsException:length = 4; index = 4长度数组
- weblogic中的类强制转换exception
- httpclientexception“org.apache.http.conn.ConnectionPoolTimeoutException:超时等待连接”
- 使用’if’语句检查后出现空指针exception
- 将有用的状态信息传递给Java中的exception有什么好方法?
- RSA BadPaddingException:数据必须以零开头