【问题标题】:Exception handling at the top layer顶层异常处理
【发布时间】:2013-10-15 12:42:38
【问题描述】:

当然,应在您认为的适当级别并适当地处理异常。假设您不知道如何处理已检查的异常,并且您将其包装在适当的自定义未检查异常中只是为了传播到顶层(假设您不处理该包装的异常和其他可能的未检查异常在某些媒介将原始异常发生的级别提高(因为您不想要或不知道如何))。更进一步,所有未处理的异常(未检查和已检查,被包装在未检查中)都达到了顶层(主方法,webapp 控制器等);我当然应该做点什么。我要做的就是通过使用日志条目来通知开发人员出了点问题,并告知用户他的请求无法正确服务(根据适用于该异常的消息使用不同的消息)。为此,我在 catch 块 RuntimeException 中使用(如果它未捕获自定义未检查异常,我将向用户发送消息“发生严重问题”或类似的信息;此类非自定义未检查异常将被缓存的可能性更大大于零,您必须就此进行沟通)。一些文章(firstsecond)建议不要在 catch 块中通过超类型捕获子类的实例(或者它只与检查的异常有关?)。如果我在 catch 块中使用了准确类型的异常,我会错过一些未经检查的异常并且应用程序会崩溃(当然,在执行日志记录和通知用户的那些 catch 块中会有重复的代码 sn-ps)。例如,我可以提供在 jsp 翻译阶段构建的 sn-p,并使用超类型来捕获该超类型的子类的实例

// some code
try {
    // body of translated JSP here...
} catch (Exception e) {
    out.clear();
    pageContext.handlePageException(e);
}
// some code  

我的问题:在顶层的 catch 块中使用 RuntimeException 向开发人员报告所有问题并向用户传达所有发生的问题是否正确?当然,例外在这种情况下的处理简化为仅通知开发人员和用户发生了问题并且没有恢复策略。也许很难将这个概念称为异常处理。请纠正我,我很欣赏关于这个概念的任何想法。

【问题讨论】:

    标签: java exception-handling


    【解决方案1】:

    我认为在你的情况下这是正确的方法。

    您最多不希望用户因看到堆栈跟踪而感到困惑,而最坏的情况是通过查看后端服务器名称、数据库凭据、数据库架构等来揭示可能的安全问题。

    您的捕获应该对用户隐藏此信息,并向用户打印有用的错误消息,以便至少他们知道问题所在。

    我对您的代码唯一关心的可能是您应该将RuntimeExceptionException 分开捕获(甚至Throwable

    try {
        // body of translated JSP here...
    }catch(RuntimeException re){
        //something unexpected
        //handle here
    } catch (Exception e) {
       //checked exception
       //handle here
    }
    

    【讨论】:

    • 非常感谢您的回答。阅读许多声称“您不应该在 catch 块中按超类类型捕获子类实例”的文章让我感到困惑。
    • 通常您不应该这样做,但在main() 或顶层有时避免向用户显示太多信息是适当的。
    【解决方案2】:

    RuntimeException 包装所有Exceptions,并在main 方法或您定义为顶级的任何地方处理它们是一种非常糟糕的做法。 Exception 的实例应尽可能靠近它们被抛出的地方处理,因为它们的存在是为了识别您可以从中恢复的错误。例如,如果您尝试打开一个文件并获得 FileNotFoundException,那么您应该对此采取措施(显示错误消息、在错误日志中添加条目等)。

    大多数时候,RuntimeException 表示编程错误 ()。通常情况下,它们表明应用程序处于不稳定状态,即使不是不可能,也很难恢复。 IllegalStateExceptionNullPointerExceptionIndexOutOfBoundsException 是此类情况的示例。

    现在,您提出的概念,即所有 RuntimeExceptions 都被捕获在顶级方法中,对于包含超过几百行代码的任何软件来说,这不是一个可行的解决方案,并且在较短的时间内是一个非常糟糕的做法程序。

    假设您有一个包含 10 万行代码的应用程序。一旦抛出异常,您的顶级方法就不可能正确处理您的异常。如果是NullPointerException,应该怎么办?它是从哪里扔的?那CloneNotSupportedException呢?您最终将拥有一个长达数十页的顶级方法,该方法将处理所有可能的异常,并使用有史以来最大的 if-then-else 语句。

    此外,如果您实现了这样的概念,您应该知道,无论何时抛出异常,您的应用程序都会进入顶级方法中的 catch 块。一旦您记录了错误,您将永远无法将控件返回给生成错误的应用程序部分,因为您将没有引发 Exception 的上下文。

    【讨论】:

    • 感谢您的回答。您建议不要将已检查异常的处理推迟到顶层(尽快执行(发送消息,创建日志条目等)),我同意。但是,在发生您提到的意外未经检查的异常(NullPointerException 等)的情况下,我应该怎么做?我同意这些未经检查的异常,因为我的编码和恢复是不可能的;但是如果我没有在顶层捕获这些异常,应用程序将崩溃,这种情况比我捕获这些异常并提供消息更糟糕跨度>
    • 您可以实现自己的UncaughtExceptionHandler,并使其记录异常跟踪,向用户显示错误消息,然后关闭应用程序。
    • 感谢您的回答和努力
    • 没有问题。您应该投票赞成对您有帮助的答案(如果有的话),并且您应该将对您帮助最大的答案标记为已接受(如果有任何答案确实解决了您的问题)。这是在 SO 上感谢人们的方式;)
    猜你喜欢
    • 2017-09-22
    • 2019-02-16
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多