【问题标题】:Handling Multiple Exceptions within a Method在方法中处理多个异常
【发布时间】:2009-12-02 21:02:30
【问题描述】:

我目前正在维护一段有点“异常快乐”的代码。基本上,任何方法或任何东西都会抛出异常。我将努力解决这个问题,但与此同时,我想知道在较小的代码块(例如方法)中处理单个异常的最佳方法是什么。这样做更好吗:

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

我意识到这是一个非常基本的问题,但是在查看了数百种方法后,每个方法都会出现异常,我开始想知道如何最好地处理所有这些方法以及这里的最佳实践可能是什么。

【问题讨论】:

    标签: java exception exception-handling methods


    【解决方案1】:

    首先,您应该只将代码放在值得例外的 try/catch 块中。例如,具有意外值不一定是异常,但尝试从不存在的文件中读取就是异常。

    要回答您的主要问题,您应该将异常代码放在同一个 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
    }
    

    【讨论】:

    • 感谢您的回答!另外,我确实理解异常价值。不幸的是,原作者确实到处抛出 java.lang.Exception,这意味着我必须处理每个异常(或者我的方法必须抛出它),所以,在这一点上,我没有选择。我将努力制定一个更加连贯的解决方案。首先从婴儿步骤开始(这个问题是其中的一部分)。
    • @Jason,没问题。很高兴看到人们在不必要的时候付出额外的努力来改进现有的代码。继续努力!
    【解决方案2】:

    您的问题的答案是:视情况而定。

    • 如果 try 块中的代码是连贯的,在发生错误时无法继续进行,则最好采用第一种方法
    • 如果代码正在采取相对不相关的单独步骤(例如解析数字)并且可以在不中止方法的其余部分的情况下恢复,那么秒方法是有意义的

    对您继承的代码的一般评论;听起来异常被滥用来传递状态,我会重构以便在可以处理它们的地方捕获异常并引入返回值或属性来处理状态。

    【讨论】:

      【解决方案3】:

      你的bMethod 不是很有用的插图。尝试改写它。无论如何,你有两个选择:

      1. 捕获异常并记录它们。
      2. 捕获异常和throw new RuntimeException(ex)(重新抛出运行时异常,将原来设置为原因)

      此外,您需要区分异常。如果您的系统有许多自定义异常,则可能是出于某种原因对其进行了定义,并且在抛出其中一个异常时会出现特定的行为。

      【讨论】:

      • "catch exceptions and throw new RuntimeException(ex)" 所以你建议用弱类型系统替换强类型系统?
      • 他似乎愿意摆脱所有这些例外。这在很大程度上取决于异常本身,以及程序流程应该如何继续。
      • 是的,我正在努力在许多情况下切换到未经检查的异常(这是有意义的)。不幸的是,该系统没有自定义例外。虽然这并不总是一件坏事,但在这种情况下必然如此。
      • 我不喜欢重新抛出未经检查的异常,要么处理异常,要么让它向上传播检查。如果将异常用作返回值的一种类型,则表示设计不佳(恕我直言)
      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

        除了已经提出的建议之外,您可能还需要考虑从函数的“肉”中提取 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());
        }
        

        这使您可以将注意力集中在您真正感兴趣的功能上,而不会妨碍您进行异常处理。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多