用Java编写带有清理操作的catch块
我在Java中找不到任何关于catch块的建议,这些块涉及一些本身可能引发异常的清理操作 经典的例子是用Java编写带有清理操作的catch块,java,exception,exception-handling,Java,Exception,Exception Handling,我在Java中找不到任何关于catch块的建议,这些块涉及一些本身可能引发异常的清理操作 经典的例子是stream.close(),我们通常在finally子句中调用它,如果它引发异常,我们要么在try-catch块中调用它来忽略它,要么声明它为rethrown 但一般来说,我如何处理以下情况: public void doIt() throws ApiException { //ApiException is my "higher level" exception try { do
stream.close()
,我们通常在finally
子句中调用它,如果它引发异常,我们要么在try-catch块中调用它来忽略它,要么声明它为rethrown
但一般来说,我如何处理以下情况:
public void doIt() throws ApiException { //ApiException is my "higher level" exception
try {
doLower();
} catch(Exception le) {
doCleanup(); //this throws exception too which I can't communicate to caller
throw new ApiException(le);
}
}
我可以做到:
catch(Exception le) {
try {
doCleanup();
} catch(Exception le1) {
//ignore?
//log?
}
throw new ApiException(le); //I must throw le
}
但这意味着我必须做一些日志分析,以了解清理失败的原因
如果我这样做了:
catch(Exception le) {
try {
doCleanup();
} catch(Exception le1) {
throw new ApiException(le1);
}
这导致我失去了把我放在第一位的le
人们在这里使用的一些成语是什么
- 在throws子句中声明较低级别的异常
- 是否在清理操作期间忽略异常
Exception ex = new Exception(le.stackTrace());
首先,在close()调用失败的情况下,确定是否确实需要从finally块中抛出(仔细考虑)。。。好吧,记录日志是很好的——但是您的API的更高层能真正解决这个问题吗?因此,对于99%的情况,您将记录次要事件,然后重新抛出主要事件 接下来,如果确实需要抛出次要异常,请确定次要异常的各种原因是否重要。这将是罕见的。因此,将次要原因设置为主要原因(使用适当的构造函数或initCause() 最后,如果您必须抛出次进程,并保留次进程和主进程的完整堆栈跟踪,那么您就需要创建一个自定义异常来处理这种情况。这很难看,因为您可能希望从不同的父类派生。如果确实出现这种情况,我建议创建一个助手类,该类能够填充目标异常的堆栈跟踪,从而基于这两个异常生成一个有意义的跟踪(确保对次要异常使用缩进,这样嵌套的异常很容易分离)
但最重要的是,我建议您使用log和rethrow主要范式。专注于解决主要问题,次要问题通常会自行解决(这里的经典示例是IO异常,它将事情弄得如此糟糕,以至于调用close()也无法成功)。我不确定。首先,有两个异常源,因此我不确定最后放在哪里;其次,我猜您指的是Throwable上的setStackTrace()方法。我们没有接受堆栈跟踪的异常构造函数。