2012-06-26 37 views
1

我有下面的代碼使用hibernate拋出一個錯誤的自定義異常,我也想在這種情況下關閉會話,因爲除非在客戶端機器上接收到異常將不捕獲。Java - 使用catch塊中的方法返回語句和拋出的異常?

public <T> T get(final Session session, final String queryName) throws RemoteException 
{ 
    final Query query = // query using given session ... 

    try 
    { 
     return (T) query.uniqueResult(); 
    } 
    catch (final HibernateException e) 
    { 
     SessionManager.logger.log(Level.SEVERE, "Could not retrieve Data", e); 
     this.closeSession(session); 
     throw new RemoteException("Could not retrieve Data"); 
    } 
} 

現在我有一個關閉會話,並拋出一個給定的異常的helper方法:

public void closeSessionAndThrow(final Session session, final RemoteException remoteException) 
    throws RemoteException 
{ 
    this.closeSession(session); 
    throw remoteException; 
} 

現在,我想我可以使用簡化了我上面的代碼:

public <T> T get(final Session session, final String queryName) throws RemoteException 
{ 
    final Query query = // query using given session ... 

    try 
    { 
     return (T) query.uniqueResult(); 
    } 
    catch (final HibernateException e) 
    { 
     SessionManager.logger.log(Level.SEVERE, "Could not retrieve Data", e); 
     this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data")); 
    } 
} 

現在我需要在catch之後添加return null;語句。爲什麼?

回答

3

closeSessionAndThrow的聲明更改爲返回RemoteException,然後「拋出」在您的客戶端代碼中調用它的返回結果。

public RemoteException closeSessionAndThrow(...) // <-- add return type here 
     throws RemoteException { ... } 

public <T> T get(...) throws RemoteException 
{ 
    try { ... } 
    catch (final HibernateException e) 
    { 
     throw this.closeSessionAndThrow(...); // <-- add "throw" here 
    } 
} 

這招數編譯器以爲它會永遠拋出任何異常是從closeSessionAndThrow返回。由於輔助方法本身會拋出異常,所以這個第二個throw永遠不會發揮作用。儘管您可以從幫助程序返回異常,但當有人忘記在調用之前添加throw時,會引發錯誤。

+0

感謝您的回答。是的,我忘了該方法不保證拋出異常!,編譯器應該如何知道這一點。 – djmj

-3

附加終於try-catch塊 終於{ 返回NULL; } - 如果執行進入嘗試塊並且結果是成功,它將返回,所以終於永遠不會被執行。 - 如果執行進入捕獲塊,終於塊得到執行後捕獲並將返回null。安全執行!

不正確答案!

+0

最後總是得到執行,即使在return語句中。 http://stackoverflow.com/questions/65035/in-java-does-return-trump-finally – djmj

+0

Ouch - 這將導致代碼總是返回null,即使在沒有異常拋出或捕獲的情況下。這不是問題所在。 –

+0

從'finally'返回''總是一個壞主意*。做一個谷歌搜索的短語,然後刪除或修改答案:) –

0

由於這種方法必須返回的東西,你應該把一個return null;

this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data")); 

但還是內catch條款或使用finally條款。

爲什麼你需要這樣做?因爲你的功能必須返回一些東西。並從此返回:

this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data")); 

並且不返回任何內容,這會導致編譯器錯誤。

1

雖然closeSessionAndThrow總是拋出遠程異常,但編譯器並沒有深入該方法來找到該異常,因此編譯器只知道它可以拋出一個RemoteException,而不會拋出異常。我也許會做這樣的事:

public RemoteException closeSessionAndThrow(final Session session, final Exception e, String msg) 
{ 
    SessionManager.logger.log(Level.SEVERE, msg, e); 
    this.closeSession(session); 
    return new RemoteException(msg); 
} 

public <T> T get(final Session session, final String queryName) throws RemoteException 
{ 
    final Query query = // query using given session ... 

    try 
    { 
     return (T) query.uniqueResult(); 
    } 
    catch (final HibernateException e) 
    { 
     throw this.closeSessionAndThrow(session, e, "Could not retrieve Data"); 
    } 
} 
3

這是一個像closeSessionAndThrow方法的問題。 JLS規則不允許編譯器推斷,由於該方法無條件拋出異常,它永遠不能正常返回。因此調用代碼必須寫成好像該方法可以返回一樣...即使「我們知道」它不會發生。

你只需要順其自然。這是Java語言不支持的「異常」控制模式,不像您/我們想要的那樣。


(在某些情況下,人們可以證明該方法總是會拋出在某些假定下一個例外。然而,由於該方法是public和在不同的類中,假設之一是,類定義並且使用該方法不會相互獨立地進行更改和編譯當然,這不是編譯器可以做出的假設......這部分解釋了爲什麼JLS規則不會試圖覆蓋這種模式

如果他們要「解決」這個問題,它會需要類似註解的東西,或者更改爲java語法來聲明輔助方法不能返回。)

+0

但我最喜歡所提供的答案。它的保證,我也可以刪除我的最後塊,我仍然不得不在其他方法中關閉會話(移動會話靠近try塊),這減少了一些代碼。 – djmj

+0

是的......它整齊地迴避了這個問題。但是,它並不適用於所有情況。例如,假設你的helper方法返回'FileNotFoundException'或'InterruptedException';即兩個不相關的檢查的異常。現在調用方法必須聲明爲拋出'Exception'。壞,壞,壞。 –

+0

@StephenC - 這是支持未經檢查的異常的另一個原因。 –