使用 try-with-resources 悄悄地关闭资源
是否可以忽略使用 try-with-resources 语句关闭资源时引发的异常?
示例:
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());
}
}
或者我应该继续在 finally
中关闭?
public static void test2(){
MyResource r = null;
try {
r.read();
}
finally{
if(r!=null){
try {
r.close();
} catch (Exception ignore) {
}
}
}
}
Is it possible to ignore the exception thrown when a resource is closed using a try-with-resources statement?
Example:
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());
}
}
Or should I continue to close in a finally
instead?
public static void test2(){
MyResource r = null;
try {
r.read();
}
finally{
if(r!=null){
try {
r.close();
} catch (Exception ignore) {
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我在 coin-dev 邮件列表上找到了这个答案:
http://mail.openjdk.java.net/pipermail /coin-dev/2009-4月/001503.html
I found this answered on the coin-dev mailing list:
http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001503.html
您可以在此处使用装饰器模式来安静地关闭资源:
我个人并不喜欢生成的语法,但这也许对您有用:
如果您愿意限制自己处理接口和杠杆,您可以做得更好动态代理类:
然后假设您有:
使用实际的资源类:
调用语法如下所示:
如果您想开始包含库(例如 AOP 启用程序),您可以做得更好。然而,这些解决方案可以与 JDK7 一起开箱即用,并且没有其他依赖项。
You could use a decorator pattern here to close the resource quietly:
I'm not personally a fan of the resulting syntax, but maybe this works for you:
You can do better if you're willing to limit yourself to dealing with interfaces and leverage a Dynamic Proxy Class:
Then assuming you have:
With an actual resource class:
Calling syntax would look like:
You can do better than this if you want to start including libraries, like AOP enablers. These solutions, however, will work out of the box with JDK7 and no other dependencies.
这是一种解决方案:
如果
ok==true
并且我们收到异常,它肯定来自close()
。如果
ok==false
,则e
来自read()
或构造函数。close()
仍会被调用,并可能抛出e2
,但 e2 无论如何都会被抑制。无需经过这样的分析,代码就具有很好的可读性。直观地说,如果
ok==true
,我们真正的工作就完成了,我们并不真正关心之后会出现什么关于资源的错误。This is one solution:
If
ok==true
and we got an exception, it definitely comes fromclose()
.If
ok==false
,e
comes fromread()
or constructor.close()
will still be called and may throwe2
, but e2 will be suppressed anyway.The code is quite readable without going through such analysis. Intuitively it says, if
ok==true
, our real work is done, and we don't really care what errors come after that regarding the resource.我实际上并不推荐这样做,但我能想到的唯一方法是检查异常的堆栈跟踪。它是否来自附近的 close 方法?
基于 https://stackoverflow.com/a/32753924/32453 任何捕获的异常都将是来自主块、关闭调用的异常或带有“抑制”关闭调用的 try 块的异常。
因此,您只需弄清楚它是否是 close call 本身的异常,这显然是 catch 行:
还有一些需要考虑的事情:
一般来说,不清楚您是否“ d 希望处理来自
close
调用的IOException
,而不是来自 try 块内部的调用。如果关闭调用意味着它没有将所有数据刷新到文件中怎么办?您可能想以同样的方式处理/对待它们。另一种选择:在块末尾附近手动关闭资源(使用自己的 try-catch)。通常允许双重关闭,因此您可以在那里捕获关闭异常。
另一种可能性:使用普通的 try-catch-finally 模式代替,这里有一些方法可以让它稍微不那么难看: Java try-finally inside try如果您没有多个资源,-catch 模式 可能是一个选项。
I don't actually recommend this but the only way I can imagine to do this is examining the Exception's stacktrace. Did it come from within a nearby close method?
Based on https://stackoverflow.com/a/32753924/32453 any caught exception will either be an "exception" from the main block, an exception from the close calls, or an exception from the try block with "suppressed" close calls.
So you just have to figure out if it's an exception from the close call itself, which is the line of the
catch
, apparently:A few more things to consider:
In general it is not clear if you'd want to handle
IOException
from aclose
call different than one from inside the try block. What if a close call implies it didn't flush all data out to the file? You may want to handle/treat them all the same.Another option: close the resource manually near the end of the block (with its own try-catch). Double-close is typically allowed so you could catch the close Exception there.
Another possibility: use normal try-catch-finally pattern instead, here are some ways to make it slightly less ugly: Java try-finally inside try-catch pattern might be an option if you don't have multiple resources.