Exception handling 例外情况下使用异常

Exception handling 例外情况下使用异常,exception-handling,refactoring,Exception Handling,Refactoring,这是一个重构问题 try { string line = GetFirstLineFromFile(); //Gets first line from a text file, this line would be a number. int value = ConvertToInteger(line); // Gets the integer value from the string. int result = DivideByValue(value); // Divides s

这是一个重构问题

try
{
  string line = GetFirstLineFromFile(); //Gets first line from a text file, this line would be a number.
  int value = ConvertToInteger(line); // Gets the integer value from the string.
  int result = DivideByValue(value); // Divides some number with the value retrieved.
}
catch(Exception ex)
{
}
我主要关心的是,在这种情况下,处理异常的最佳方法是什么。当然,将整个过程包装在一个try-catch中就像是说我期望所有事情都会出现异常。一定有什么地方我们捕捉到了一般异常,对吧?

只是不要捕捉到“一般异常”

您如何处理任何异常并知道如何保持应用程序处于干净状态? 它隐藏了虫子,这真是个坏主意


阅读上的这一系列文章。

您需要考虑可以从
try
块中的方法抛出哪些异常,以及可以在当前抽象级别处理哪些异常

在您的例子中,我希望
getFirstLineFromFile
方法可以抛出您希望在这里捕获的异常。现在,您是包装并重新显示异常,还是采取其他操作,取决于您是否能够在这个级别实际处理异常。考虑一下你有一个默认文件可以退回到的情况,该方法可能只是记录一个警告并继续使用默认值。或者,如果整个应用程序都是基于读取用户提供的文件,那么这很可能是一个致命的异常,应该传播到顶层并传达给那里的用户

没有像“总是扔”或“从不扔”这样的硬性规定;一般来说,我认为每当有异常类型的情况被认为是该方法的正常结果时,就应该抛出异常,因此不能通过该方法的返回类型来充分描述。(例如,返回布尔值的
isValidDbUser
方法可能能够像处理
SQLException
返回false一样处理
SQLException
;但是返回int的
getNumProductsRegisteredDB
几乎肯定会传播异常)。

不要听(部落)很多人会告诉你永远不要在一个大的通用块中捕获多个异常。在某些情况下,这是进行一般错误处理的一种完全合理的方法,这就是为什么语言中存在这样做的能力

将有一些异常,您可以对它们做一些特定和有用的事情(例如,在catch块中从它们中恢复)。这些是您希望单独捕获的异常类型,并且尽可能靠近它们发生的位置

但在现实生活中,你将面临的大多数异常都是完全出乎意料的、未经检查的异常。它们是程序员错误(bug)、断言失败、硬件故障、网络连接中断等的结果

您应该防御性地设计软件,通过指定特定的“阻塞点”来处理这些不可预测的异常,同时将对应用程序其余部分的中断降至最低。(请记住,在许多情况下,“处理”异常通常只意味着中止当前操作并记录错误,或者告诉用户发生了意外错误。)

例如,如果您的程序将文件保存到磁盘,您可以将整个保存操作包装在一个try块中,以捕获保存过程中出现的错误:

try {
   // attempt to perform the save operation
   doSave();

} catch (Throwable t) {
   // tell the user that the save failed for unexpected reasons
   // and log the error somewhere
   informUser("save failed!");
   log("save failed!", t);

} finally {
   // last minute cleanup (happens whether save succeeded or failed)
   ...
}
请注意,我们在这里选择了一个很好的阻塞点方法(doSave()),然后阻止任何超出此点的意外错误冒泡。阻塞点表示单个可取消的操作(保存)。如果您遇到意外的异常,该操作显然是失败的,但不管阻塞点的另一端发生了什么,应用程序的其余部分都将保持良好状态

还要注意,这个习惯用法并没有阻止您在doSave()中的某个地方进一步处理某些异常。因此,如果有可能抛出的异常可以从中恢复,或者希望以特殊方式处理,请在doSave()中继续执行。但其他一切,你都有你的瓶颈

您甚至可能希望在主方法中为整个程序设置一个常规的未捕获异常处理程序:

public static void main(String [] args) {
    try {
       startApplication();
    } catch (Throwable t) {
       informUser("unexpected error! quitting application");
       log("fatal application error", t);
    }
但是,如果你明智地设置了其他瓶颈,那么到目前为止,没有例外会出现。如果希望完成常规错误处理,还可以创建一个重要线程并将其分配给重要线程,包括主线程或AWT线程(如果使用Swing)



TL;博士不要相信你应该总是尽可能地捕捉异常的教条。有时,您希望捕获并处理特定的异常,有时您希望使用阻塞点捕获并处理“可能出错的任何其他内容”。

我知道我不会编写这样的代码。但是,如果我删除了all wrapping try catch块,那么这些函数中的每一个都会进行某种异常处理。覆盖所有预期的异常并为它们编写catch块是否可行?您调用的方法应该有一组已定义的异常抛出。然后只捕获已定义的异常…通过C#读取CLR后,异常处理肯定不像人们使用它那样简单。你能告诉我什么时候你会捕获一般异常吗?到目前为止,我一直在做的是为特定异常添加catch语句,然后创建一个泛型异常catch块。为什么要捕获泛型异常?你能用它做什么?在我看来,你唯一可以合法地这样做的时间是在你的程序/webapp的最高层(或者可能是非必要的操作),以便将其转化为适合用户的响应。就webapp而言,至少你不希望整个应用程序都崩溃。否则,如果要确保精确地执行清理代码,请使用
finally
块。捕获特定的异常确实表明开发人员认为