简体   繁体   English

处理方法中的多个异常

[英]Handling Multiple Exceptions within a Method

I am currently working on the maintenance of a piece of code that is a little bit "Exception Happy." 我目前正致力于维护一段有点“异常快乐”的代码。 Basically, ever method or anything throws Exception. 基本上,任何方法或任何东西抛出异常。 I'm going to work to take care of that, but, in the meantime, I am wondering what is the best way to handle individual exceptions within a smaller block of code, such as a method. 我将努力解决这个问题,但与此同时,我想知道在较小的代码块中处理个别异常的最佳方法是什么,例如方法。 Is it better to do something like this: 做这样的事情更好:

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

Or something like this: 或类似的东西:

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.
  }
}

I realize this is a pretty basic question, but after looking at hundreds of methods with Exceptions coming out of every one, I'm starting to wonder how best to handle all of them and what a best practice may be here. 我意识到这是一个非常基本的问题,但是在查看了数百种带有异常的方法之后,我开始想知道如何最好地处理所有这些方法以及最佳实践可能在这里。

First off, you should only put code in try/catch blocks that is exception worthy. 首先,您应该只将代码放在try / catch块中,这是非常值得的。 For instance, having an unexpected value is not necessarily an exception, but trying to read from a file that doesn't exist is. 例如,具有意外值不一定是例外,但尝试从不存在的文件读取是。

To answer your main question, you should put the exceptionable code in the same try {} block and catch specific questions in order of granularity in multiple catch blocks after the main try. 要回答您的主要问题,您应该将异常代码放在同一个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
}

The answer to your question is: it depends. 你的问题的答案是:它取决于。

  • if the code in the try block is coherent where it makes no sense to proceed in the event of an error, the first approach is best 如果try块中的代码是连贯的,在发生错误的情况下继续进行是没有意义的,那么第一种方法是最好的
  • if the code is taking seperate steps that are relatively unrelated (parsing numbers for instance) and can be recovered without aborting the rest of the method the seconds appraoch makes sense 如果代码采取相对不相关的单独步骤(例如解析数字)并且可以在不中止方法的其余部分的情况下恢复,那么秒数appraoch是有意义的

A general remark on the code you inherited; 关于您继承的代码的一般说明; it sounds like exceptions are abused to pass state around, I would refactor so that exceptions are caught at the spot where they can be handled and introduce return values or attributes to handle the state. 听起来好像异常被滥用来传递状态,我会重构,以便在可以处理它们的位置捕获异常并引入返回值或属性来处理状态。

your bMethod isn't very useful illustration. 你的bMethod不是很有用的插图。 Try to reprase it. 尝试重新编写它。 Anyway, you have two options: 无论如何,你有两个选择:

  1. catch exceptions and log them. 捕获异常并记录它们。
  2. catch exceptions and throw new RuntimeException(ex) (rethrow a runtime exception, setting the original as a cause) 捕获异常并throw new RuntimeException(ex) (重新抛出运行时异常,将原始设置为原因)

Also, you will need to differentiate between exceptions. 此外,您还需要区分异常。 If your system has many custom exceptions, they are probably defined for a reason, and specific behaviour is expected when one of them is thrown. 如果您的系统有许多自定义异常,则可能是出于某种原因定义了它们,并且在抛出其中一个异常时会出现特定的行为。

If the try/catch block isn't adding useful information, just allow the method to throw the exception and have it handled where the caller can sensibly do something with the exception. 如果try / catch块没有添加有用的信息,只需允许该方法抛出异常并将其处理到调用者可以明白地执行异常操作的地方。 This could cut down the number of try/catch significantly (by an order of magnitude). 这可以显着减少尝试/捕获的数量(按一个数量级)。

BTW a trick for rethrowing any exception is. BTW重新抛出任何异常的技巧是。

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

In addition to the suggestions already made you may also want to consider extracting try/catch blocks from the "meat" of the function. 除了已经提出的建议之外,您可能还需要考虑从函数的“肉”中提取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());
}

This lets you focus your attention on the function you are really interested in without the exception handling getting in your way. 这使您可以将注意力集中在您真正感兴趣的功能上,而不会遇到异常处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM