处理多个异常但避免重复代码

时间:2014-01-30 13:10:31

标签: java exception-handling

我想知道如何处理异常并仍然避免重复代码。以下是我对处理这种情况的看法。

重复代码避免情况(我不喜欢在这里使用instanceof)。

try{

    //some code which might throw multiple different exceptions. 

} catch(Exception e) {

    //do something here

    if(e instanceof IOException) {
       // do something only when this type exception occurred.
    } else if( e instanceof SQLException){
      // do something only when this type of exception occurred.
    } else if( e instanceof SomeCustomExceptionMaybe){
       // do something only when this type of exception occurred.
    }

   //continue exception handling here.
} 

VS

没有实例(我真的不喜欢有重复的代码)。

try{

     //some code which might throw multiple different exceptions.

} catch(IOException e1) {
    // The order must always be this.
    // do something general for each exception
    // do something only with this exception 
    // do something general again.
} catch(SomeCustomExceptionMaybe e2) {
    // The order must always be this.
    // do something general for each exception
    // do something only with this exception 
    // do something general again.
} //and so on

ps:在给出答案时尽量避免使用java 7异常处理:

catch(IOException | SomeOtherTypeException | AnotherTypeException)

编辑:我没有使用java 7,这就是为什么我要求避免基于java 7的响应。

3 个答案:

答案 0 :(得分:2)

像第一个例子中那样捕获原始Exception是一个非常糟糕的解决方案。 Exception是应检查和处理的已检查异常(IOException等)的父类;但对于RuntimeException来说,这也是信号编程错误(没有检查参考无效或数组索引等)的信号,通常不会被捕获 - 而是更正。

此外,当Exception块中的代码稍后被修改并抛出新的异常时,捕获非常宽泛的try可能会产生一些意想不到的副作用:它们将被现有的静默捕获catch阻止。

因此,我认为为每种不同类型的异常设置一个独特的catch块会好得多,即使它意味着复制(在Java7之前)一些错误处理代码。

当然,限制此代码重复的最明显方法是使用常用方法将其外部化:

try {
    ... 
} catch (FooException fe) {
    handleException(fe);
} catch (BarException be) {
    handleException(be);
} 
...

private void handleException(Exception e) {
    ...
}

如果严格按照相同的方式处理所有异常,那就没关系。但是,只要您想根据确切的异常类型执行不同的操作,就需要使用instanceof运算符,这种运算符始终具有很强的代码味道。

总之,我会将错误处理代码保留在catch块中,即使它现在意味着一些代码重复 - 从长远来看它仍然会更强大。

答案 1 :(得分:2)

第一个明显的解决方案是使用方法:

catch(IOException e1) {
    doSomethingGeneral(); 
    // do something only with this exception 
    doSomethingGeneralAgain();
}

虽然留下了一些重复。以冗长为代价,因为Java还没有lambdas(但是在Java 8中),你可以在一些匿名类中提取特定的行为:

catch(IOException e1) {
    handleException(new Runnable() {
        @Override
        public void run() {
            // do something only with this exception
        }
    });
}

其中handleException()的工作方式如下:

private void handleException(Runnable specificBehavior) {
    // do something general
    specificBehavior.run();
    // do something general again
}

我迫不及待地等待Java 8,这将允许重写为:

catch(IOException e1) {
    handleException(() -> {
        // do something specific
    });
}

答案 2 :(得分:0)

我还没有测试过以下方法,但也许有帮助:

try{

     //some code which might throw multiple different exceptions.

} catch(Exception e) {
    if ((e instanceof IOException) || (e instanceof SomeCustomExceptionMaybe)) {
        //do something
    } else {

    }
}