2012-03-08 63 views
4

我很困惑,捕获和重新抛出异常与将它抛到第一位相比会发生什么。Java - 抛出异常和捕获和重新抛出异常之间的区别例外

例如

private void testMethod() throws Exception 
{ 
    //some bad code here 
} 

与:

private void testMethod() throws Exception 
{ 
    try 
    { 
     //some bad code here 
    } 
    catch (Exception e) 
    { 
     throw e; 
    } 
} //end testMethod() 

这是保存错误消息的堆栈跟踪?我试图设置一个例子,但没有看到两者之间有任何不同的输出。

感谢您的帮助。

回答

0

没有区别。除非你想在重新投掷之前用它做一些事情(例外情况)。

0

我不认为有很大的区别,但对于什么值得我更喜欢第一个。

除非您可以做些什么,否则您不应该捕获异常,或者您的类是一个超出其范围的异常应该传播的边界(例如捕获所有异常和路由器用户访问友好错误页面的Web控制器)。

简单地捕捉和重新投掷是浪费击键。它没有添加任何信息,也没有任何建设性。

一个例外就是捕获一个检查的异常并将其作为未检查的异常封装。否则,避免第二个习语。

1

使用此方法,您可以修改例外。例如,你可以给它一个更具体的信息。

与此说,你应该因为

  • 它群集最多的为没有额外的服务代码(正常情况下),一般不采用这种技术
  • 您应该只使用try-catch块,其中实际上必要的,因为它可以在执行减缓
1

标准的原因赶上并重新抛出异常是:

  1. 记录事件和异常。
  2. 由于异常(但通常最好在finally块中完成)做一些清理。
  3. 将异常封装在一个更合适的异常中(也就是说,您的processAccount()方法可能更适合抛出AccountException(或某些此类)而不是DbException)。
2

正如其他人所说,在你的例子中没有区别,应该避免第二种形式。

唯一有时候有意义的地方是你需要捕捉一些例外的地方,并让其他人得到向上抛出。由于Java的异常处理语法是有限的,有时你可以这样做:

try { 
    somePieceOfCode(); 
} catch(RuntimeException e) { 
    throw e; 
} catch(Exception e) { 
    handleException(e); 
} 

如果somePieceOfCode抛出许多不同的检查型异常的不具有公共基类(超过Exception等),但需要这有时做以相同的方式处理。你可能不想只抓到Exception,因为那也会吸引像NullPointerException这样的东西,你可能更喜欢那些例外情况。

此代码将让所有RuntimeExceptions冒泡向上,但处理所有其他例外。

这个成语很少有不寻常的,并不是每个人都喜欢它,但你可能会在某些地方看到它。

0

捕获然后重新抛出的主要好处之一是在另一个特定于域的异常中包装异常,因此调用代码不必担心实现的特定问题,并且可以捕获特定于库的异常。

在给出的例子中没有真正的好处,但是在其他库中可以看到这样一个好处的一个好例子 - 我们可以看一下Hibernate。

Hibernate捕获泛型SQLException,然后检查该对象以确定异常的真正原因,然后将其包装在Hibernate特定的异常中,该异常更详细地描述了问题的起因。但是,如果您只是捕获异常并抛出相同的异常,那么您最有可能这样做,因此您可以首先记录异常(尽管这不一定是最佳方法) 。

5

您的两个代码示例之间的行为没有差异。 (特别是,在创建异常时记录堆栈跟踪,而不是在抛出异常时发生,因此重新抛出的异常仍然具有原始堆栈跟踪)。通常,人们因此使用更简单的习语。

这并不是说重新投掷没有它的用​​途。举例来说,如果你要处理除了FooBarExceptions所有的异常,你可以写:

try { 
    // bad code 
} catch (FooBarException e) { 
    throw e; 
} catch (Exception e) { 
    e.printStackTrace(); 
} 

或者如果处理异常的决定是不是简单地检查它的类型更复杂,你可以简单地抓住它,并重新抛出,如果事实证明,你不能处理它:

for (int attempts = 0; attemps < 6; attempts++) { 
    try { 
     return crankyMethod(); 
    } catch (Exception e) { 
     if (fatal(e)) { 
      throw e; 
     } else { 
      // try again 
      continue; 
     } 
    } 
} 

值得注意的是,当人们说重新抛出,一些平均抛出一个不同的异常,如下面的例子:

for (int i = 0; i < array.length; i++) { 
    try { 
     process(array[i]); 
    } catch (Exception e) { 
     throw new RuntimeException("Could not process element at index " + i, e); 
    } 
} 

此模式的优点是用可能相关的附加信息(在上例中:无法处理哪些数据)修饰原始异常。请注意,原始异常传递给新构造函数,因此其堆栈跟踪不会丢失。