是否可以设置一个可选的异常被捕获?
换句话说,一个例外可以:
为了可视化,我有一个ReportedException
,它只是RuntimeException
的一个简单子类,并且希望能够在需要时捕获它:
try
{
hideWindow();
}
catch (ReportedException ex)
{
// Window could not be hidden.
// Exception has already been caught and logged by parseInput(),
// and now we're going to do something more.
printAdditionalErrorMessage();
}
注意:我编辑了上面的示例以更好地适应我的问题。
如果结果不相关则跳过捕获:
hideWindow(); // We don't care if there was an error or not.
openAnotherWindow();
我知道我可以将catch块留空,并且具有与上面相同的功能,但我经常使用ReportedException
,这会使我的代码高度不可读。
如果这是不可能的(我怀疑它是),你会推荐什么替代/解决方案?
P.S。示例中使用的方法名称只是foo和bar。
编辑:我知道我不需要捕获RuntimeExceptions。我想要的是在它们发生时忽略它们。
答案 0 :(得分:3)
例外情况应该用于特殊情况。
从您的示例中,如果未隐藏的窗口是典型事件,则不应抛出异常。如果这是您的函数,则使用返回值来指示它是否成功而不是抛出异常。然后,当您不关心它是否成功时,您可以安全地忽略返回值。
如果您无法控制该方法,则可以将其包装在另一个捕获异常并将其转换为返回值的方法中。 E.g。
private boolean tryHideWindow() {
try {
hideWindow();
}
catch (ReportedException ex) {
return false;
}
return true;
}
如果您需要一些异常参数来确定要执行的操作,那么您可以返回异常。
private static class MyReturnType {
private final Throwable thrown;
private final OrigRtnType returnVal;
public MyReturnType(Throwable thrown) {
this.thrown = thrown;
this.returnVal = null;
}
public MyReturnType(OrigRtnType returnVal) {
this.thrown = null;
this.returnVal = returnVal
}
public boolean wasExceptionThrown() {
return thrown != null;
}
}
private MyReturnType tryHideWindow() {
try {
OrigRtnType returnVal = hideWindow();
}
catch (ReportedException ex) {
return new MyReturnType(ex);
}
return new MyReturnType(returnVal);
}
这是你问题的答案,但不一定是个好主意。由于其他人会对评论进行双重评论,因此使用程序流程的例外情况并不理想。
答案 1 :(得分:2)
我对如何使用ThreadLocal感到有点模糊(并且很容易出现其他类似的问题),但是这样的话:
public class IgnorableException {
static class DontIgnoreCount {
int count;
}
// Thread local variable containing each thread's ID
private static final ThreadLocal<DontIgnoreCount> dontIgnoreCount =
new ThreadLocal<DontIgnoreCount>();
static void incrementDontIgnore() {
DontIgnoreCount counter = dontIgnoreCount.get();
if (counter == null) {
counter = new DontIgnoreCount();
dontIgnoreCount.set(counter);
}
counter.count++;
}
static void decrementDontIgnore() {
DontIgnoreCount counter = dontIgnoreCount.get();
// Must not be null here
counter.count--;
static bool shouldSignal() {
DontIgnoreCount counter = dontIgnoreCount.get();
return counter.count > 0;
}
}
要使用,请在try范围的早期调用DontIgnoreCount.incrementIgnoreCount(),并在最终范围的后期调用DontIgnoreCount.decrementIgnoreCount()。
当发出遵循此协议的异常时,仅在shouldSignal返回true时发出信号。
void iWannaCatchException() {
try {
IgnornableException.incrementDontIgnore();
int x = someOptionallySignallingMethod();
}
catch (...) {
...
}
finally {
IgnorableException.decrementDontIgnore();
}
}
void iDontWannaCatchException() {
int x = someOptionallySignallingMethod();
}
int someOptionallySignallingMethod() {
if (somethingBad) {
if (IgnorableException.shouldSignal()) {
throw new BadException();
}
}
return 42;
}
请注意,上面未显示的是您必须添加的任何throws
子句,以保持编译器满意。这种机制不会消除对这些机制的需要。
您还可以使用一个观察者对象替换一个委托/观察者方案,将简单计数器替换,并将一条消息传递给观察者并抛出异常。但是,这本身(没有耦合异常/尝试范围)将不允许将堆栈吹走到适当的恢复点。
答案 2 :(得分:0)
听起来你想要使用流量控制的异常,而不是报告真正特殊情况。
通常不赞成使用流控制的异常。常见的方法是将成功/失败指示作为函数的返回值返回。
答案 3 :(得分:0)
您可以使用以下内容:
try{
hideWindow();
}catch (ReportedException ex){
// ingore
}catch (NullPointerException ex){
killWindow();
}finally {
//to do something more.
}