3

什么时候用“catch”,什么时候用“throws”?

try {
    //stuff
} 
catch (MyException me) {
    //stuff
}

相对

public void doSomething() throws MyException {
    //stuff
}

在“抛出”的情况下,将我的捕获放在调用堆栈的哪里?

Main
    ----- Function 1
        ----- Function 2
            ----- Function 3 (generate exception)

如果我将异常从函数 3 传播到函数 2,为什么函数 2 不应该这样做?所以最后我将最终管理“main”中的所有异常,我认为将所有代码放在 try 块中并不是一个好的做法,不是吗?

那么在“catch”和“throws”之间进行选择的逻辑方式是什么?在第二种情况下,我应该将我的捕获放在调用堆栈中的什么位置?

4

3 回答 3

2

它们基本上是相反的。throws表示允许函数抛出异常;catch意味着一个块(the try)块期望一个异常可能被抛出,并准备好处理它。

拿球来比喻,投手throws是接球手所期望的例外。接球手接住catches球并以某种方式处理它。(好吧,也许这个比喻有点不对劲,因为接球手通常通过将球扔回投手来处理球。:))在这里,投手是一种方法,而接球手是一个try-catch-[finally]积木。

于 2013-05-03T18:32:11.643 回答
0

当方法的调用者需要捕获或传递它时,您应该声明该方法抛出一个已检查的异常。每当您准备好立即处理该异常时,您都应该捕获该异常。

例如,如果您正在编写一个具有图形界面的程序,该程序还具有从文件读取的核心,则核心类无法告诉用户出现错误,这就是图形界面的工作。因此,诸如getSomethingFromFile()核心程序中的方法可能会抛出IOException. 如果图形界面调用getSomethingFromFile()并确定存在读取错误,则图形界面可以向用户显示一个对话框,以便随时准备好捕获异常。在这种情况下,getSomethingFromFile()调用应该包含在 try/catch 中。

于 2013-05-03T18:37:02.443 回答
0

如果您要采用一种throw - catch方法来处理错误,那么实际的错误处理必须由负责执行此操作的组件来完成,特别是因为这允许您将逻辑封装在它所属的位置。

异常被某个类捕获,该类知道如何处理它,以及必须采取的行动过程。在某些特定情况下,您可以通过将异常包装在另一个异常中来重新引发异常(将异常设置为其原因)以任何 ORM 为例,任何低级异常都被包装在例如PersistenceException可以以 SQLSyntaxException 作为其原因的 a 中。

throws如果您没有适当的工具来管理特定上下文中的异常,并且您希望将其传播到可以正确管理的更高层/层,那么它就会发挥作用。

让我举一个“大图示例”:

  1. 将实体保存到数据库
  2. 通讯错误
  3. 抛出异常,因此您的持久性对象必须处理它。
  4. 捕获它,包装它并将其作为您自己的异常之一重新抛出(我反对让持久性异常传播到更高层......但这只是我)。
  5. 持久性会引发模型捕获的异常。
  6. 模型重试该操作。
  7. 另一个失败(相同的wrap + throw)。
  8. 模型会通知失败并将报告提升到视图。这就是我被“知道”该做什么的人抓住的意思。
  9. 该视图向用户显示“今天不保存,抱歉”。

该示例包含两个案例throwcatch我希望它有助于澄清。

于 2013-05-03T18:41:36.700 回答