在一个方法内处理多个异常

问题描述:

我目前正在维护一段有点“异常快乐”的代码。基本上,任何方法或任何抛出异常。我将努力处理这个问题,但同时,我想知道在更小的代码块(如方法)中处理个别异常的最佳方法是什么。它是更好地做这样的事情:在一个方法内处理多个异常

public void aMethod() 
    try { 
    //Lots of code in here. Many lines. 
    } catch(Exception e) { 
    // TODO - Handle All Exceptions, but fairly generically 
    } 
} 

或者是这样的:在寻找

public void bMethod() { 
    try { 
    // One line of code. 
    } catch(Exception e) { 
    // TODO - Handle a specific Exception (may even involve rethrowing it with more information) 
    } 

    // More code. 

    try { 
    // Another line of code. 
    } catch(Exception e) { 
    // TODO - Handle another specific exception. 
    } 
} 

我意识到这是一个非常基本的问题,但毕竟在数以百计的方法有例外出来的每其一,我开始怀疑如何最好地处理所有这些问题,以及这里可能采取的最佳做法。

首先,您应该只将代码放在try/catch块中,这是值得的例外。例如,有意想不到的值不一定是个例外,但是试图从一个不存在的文件中读取。

要回答你的主要问题,你应该把异常代码放在同一个try {}块中,并在主尝试之后按照多个catch块的粒度顺序捕获特定问题。

//Regular code that doesn't need to be covered by a try/catch block 

try { 

    //critical code only 

} catch (NullPointerException npe) { 
    //Code 
} catch (RandomException re) { 
    //code 
} catch (Exception e) { 
    //code 
} 
+0

感谢您的回答!另外,我的确了解异常值。不幸的是,原作者在任何地方都会抛出java.lang.Exception,这意味着我必须处理每个异常(或者我的方法必须抛出异常),所以在这一点上,我没有得到一个选项。我将致力于一个更加连贯的解决方案。首先从婴儿步骤开始(这是本问题的一部分)。 – JasCav 2009-12-02 21:20:17

+0

@Jason,没问题。很高兴看到人们不需要额外努力改进现有代码。保持良好的工作! – 2009-12-02 21:40:46

你的bMethod是不是很有用的说明。尝试重新编辑它。无论如何,你有两种选择:

  1. 捕获异常并记录它们。
  2. 捕捉异常和throw new RuntimeException(ex)(重新抛出运行时异常,放置原稿的一个原因)

此外,你需要异常区分。如果您的系统有很多自定义异常,则可能是因为某个原因而定义的,并且在引发其中一个异常时会发生特定行为。

+0

“捕获异常并抛出新的RuntimeException(ex)”,因此您建议用弱类型的系统替换强类型的系统? – rsp 2009-12-02 21:19:02

+0

他似乎愿意摆脱所有这些例外。它很大程度上取决于例外情况,程序流程应该如何继续。 – Bozho 2009-12-02 21:22:14

+0

是的,我正在努力在很多情况下切换到未经检查的异常(在哪里有意义)。不幸的是,该系统没有自定义例外。虽然这并不总是一件坏事,但它必然是在这种情况下。 – JasCav 2009-12-02 21:23:23

你的问题的答案是:这取决于。

  • 如果try块中的代码是一致的地方是没有意义的错误的情况下进行,第一种方法是最好的
  • 代码是否采取有相对无关单独的步骤(解析例如数字),并且可以在不中止该方法的其余部分的情况下恢复

关于您继承的代码的一般注释;这听起来像是异常被滥用以传递状态,我会重构,以便在可以处理异常的位置捕获异常,并引入返回值或属性来处理状态。

如果try/catch块没有添加有用的信息,只要允许该方法抛出异常并在调用者可以明智地对异常做些什么的情况下处理。这可以显着减少try/catch的数量(一个数量级)。

顺便说一句,重新抛出任何异常的技巧是。

try { 
    // do something 
} catch (Throwable t) { 
    Thread.currentThread().stop(t); // rethrow any exception. 
} 

除了已经提出的建议,您可能还想考虑从函数的“肉”中提取try/catch块。

public void delete(Page page) { 
    try { 
     deletePageAndAllReferences(page); 
    } 
    catch (Exception e) { 
     logError(e); 
    } 
} 

private void deletePageAndAllReferences(Page page) throws Exception { 
    deletePage(page); 
    registry.deleteReference(page.name); 
    configKeys.deleteKey(page.name.makeKey()); 
} 

private void logError(Exception e) { 
    logger.log(e.getMessage()); 
} 

这让你专注于你真正感兴趣的功能,而不需要异常处理。