让异常向上移动调用堆栈有什么价值?

时间:2015-05-17 23:24:23

标签: java exception try-catch

我只是reading about try-catch blocks和异常处理,我在"传播IOExceptions"一段让我困惑的部分。 Jenkov说如果方法C抛出一个IOException - public void MethC() throws IOException{} - 但没有try-catch来处理它,它会将调用堆栈汇总到一个可能有一个{的调用方法{1}}处理异常

try-catch块的重点似乎是处理一个异常,如果未处理,会导致程序崩溃吗?好吧,那么为什么让异常将调用堆栈回滚到链上某个地方的try-catch-finally?有什么价值?如果有的话,在我看来,让异常卷起来,而不是立即处理,只会危及程序,形成不良,造成效率低下或效率低下。

4 个答案:

答案 0 :(得分:2)

只要您的设计需要,就可以让异常渗透调用堆栈。一个简单的示例是,如果您的main方法在调用周围有一个try / catch块,可能会有一个非常深的调用堆栈。如果在任何时候发生错误,它可以throw例外,程序可以catch main中的browser.get("https://www.voilanorbert.com") inputName = wait.until(EC.presence_of_element_located((By.ID, "form-search-name"))) inputName.click() inputName.send_keys(sheet.cell_value(i,0)) inputDomain = wait.until(EC.presence_of_element_located((By.ID, "form-search-domain"))) inputDomain.click() inputDomain.send_keys(sheet.cell_value(i,2)) norbertsearch = browser.find_element_by_name("search") norbertsearch.click() 优雅地结束说“抱歉,发生以下重复,所以程序结束”

永远不会捕获异常并让程序异常终止是不好的设计,但是如果在实例中有意义的话,从实际异常发生的位置捕获它会有很多错误。

通常问题发生在代码的深处,并且处理它的正确方法(显示对话框?打印错误?安静地处理它?)可能因不同的调用路径而不同,并且可以选择做什么在调用堆栈的其他地方。

答案 1 :(得分:2)

通常,应该在调用堆栈中能够处理它的位置处理异常。

例如,假设您有一个采用文件路径的库方法并以public static byte[] readFile(final String filePath) throws IOException { final InputStream inputStream = new FileInputStream(filePath); ... } 的形式返回文件的全部内容:

new FileInputStream(filePath)

这个函数无法“处理”不存在的文件;如果FileNotFoundException引发IOExceptionfilePath的子类型),那么此函数可以做的最好的事情是通知其调用者。调用者可以获得有关filePath来自何处的更多信息,以及缺少文件时的含义;例如,如果用户键入了readFile,那么这可能意味着程序需要向用户显示一条消息,让他/她知道可能的拼写错误。关键是,struct Student { string name; int score; bool operator<(const Student& rhs) const { return score > rhs.score || (score == rhs.score && name < rhs.name); } }; 没有任何信息,无法做出正确的决定。所以它应该让异常传播给一个可以调用的调用者。

答案 2 :(得分:2)

  

try-catch-finally块的重点似乎是处理一个异常情况,这个异常会在未处理的情况下导致程序崩溃吗?

不完全是。异常并不总是导致程序崩溃,它可以“只是”导致它的某些部分无法正常工作。确实try-catch-finally用于处理异常。

  

为什么让异常将调用堆栈回滚到链上某个地方的try-catch?有什么价值?

因为有时候发生异常的方法不适合决定如何处理它。

我将给出一个示例:查看方法Integer.parseInt(String s),它需要String并尝试根据其内容将其转换为int。由于这是在运行时完成的,并且您无法提前知道字符串是什么,因此您必须考虑字符串不是数字,例如,如果它来自用户输入。如果它不是可解析的字符串,您希望该方法如何处理它?为什么要决定它不是设计执行的操作的结果?

这就是该方法抛出NumberFormatException - if the string does not contain a parsable integer的原因。调用该方法的人有权决定应该做什么,因为该方法仅用于将字符串转换为数字。它可以要求换一个新字符串,因为最后一个字符串无效,或者只使用默认数字作为一种占位符。

现实生活中的比喻:老板告诉他的秘书安排在某个特定日期与员工会面,秘书发现该员工正在那个假期休假。秘书应该自己处理这个情况吗?可能不是。相反,他们会按照“InvalidMeetingTime”的方式向他们的老板“抛出异常”并让老板决定该怎么做。

  

在我看来,让异常卷起链接,而不是立即处理它只会危及程序,形成不良,导致效率低下或效率低下。

这就是调用范围有责任正确委派事件的原因。要么自己处理它,要么将它向上传递,直到它处理它为止。

请参阅Lesson: Exceptions

答案 3 :(得分:0)

有时候让异常回滚堆栈会有很多原因(Service,Restfull api等)。假设您有一个显示或解析文件的方法并将文件名作为参数,您不知道谁将使用您的方法或因此通过抛出异常,您给开发人员另一个机会来显示他的消息或句柄按照他的意愿。