2012-03-08 59 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); 
    } 
} 

此模式的優點是用可能相關的附加信息(在上例中:無法處理哪些數據)修飾原始異常。請注意,原始異常傳遞給新構造函數,因此其堆棧跟蹤不會丟失。