2016-06-10 65 views
0

我已經寫了一個方法,它在try語句中返回一些值。在catch中,我調用了handleException,它將具有理解異常並重新拋出新異常的轉換邏輯。這裏handleException總是拋出異常,getXYZ()仍然給出編譯時錯誤,期望返回語句。我沒有處理異常,我只是拋出新的異常,所以爲什麼該方法想要返回語句。爲什麼一個方法需要catch語句中的返回語句,即使catch語句重新拋出異常

public String getXYZ(String input) { 
    try { 
     return getFromDAO(input); 
    } catch (Exception e) { 
     handleException(e); 
    } 
} 
private void handleException(Exception e) { 
    try { 
     throw e; 
    } catch(SomeException se) { 
     throw new MyRuntimeException("MyException message", se); 
    } catch(SomeOtherException soe) { 
     throw new MyRuntimeException("MyException message", soe); 
    } 
} 

此方法的其他版本編譯。

public String getXYZ(String input) { 
    try { 
     return getFromDAO(input); 
    } catch (Exception e) { 
     throw e; 
    } 
} 
+1

在另一個註釋中,您可能想要在方法參數中添加一些throws子句。 [請參閱此處的示例](https://docs.oracle.com/javase/tutorial/essential/exceptions/declaring.html)稍後將幫助您確保嘗試捕獲這些「異常」對象 – Draken

回答

4

你是不是在catch塊扔東西,你調用你的處理函數,這最終將導致新的異常被拋出,但在getXYZ實際代碼catch是做一個函數調用。如果你改變handleException以後在某些情況下不會拋出異常,那麼getXYZ會返回什麼呢?

+0

什麼是使用handleException方法的正確方法?它應該返回異常對象而不是拋出它,然後getXYZ拋出異常? – deepak

+0

爲什麼不把這些'catch'塊放到'getXYZ'中,而不需要''只是將一個異常類型轉換爲另一個異常類型的'handle'函數? –

+0

我必須在一個類的許多方法中捕捉到相同的異常,所以我正在編寫一個單獨的私有方法來執行異常轉換。 – deepak

1

解決此問題的一種方法是向編譯器明確指出您期望拋出異常。

public String getXYZ(String input) { 
    try { 
     return getFromDAO(input); 
    } catch (Exception e) { 
     throw handleException(e); // compiles ok. 
    } 
} 

private RuntimeException handleException(Exception e) { 
    try { 
     throw e; 
    } catch(SomeException se) { 
     return new MyRuntimeException("MyException message", se); 
    } catch(SomeOtherException soe) { 
     return new MyRuntimeException("MyException message", soe); 
    } catch(RuntimeException re) { 
     return re; 
    } catch(Exception e2) { 
     return new MyRuntimeException("MyException message", e2); 
    } 
} 

BTW一種替代的方法是不是在所有包裝異常,並留下異常,因爲它是。

public String getXYZ(String input) { 
    try { 
     return getFromDAO(input); 
    } catch (Exception e) { 
     throw rethrow(e); // compiles ok. 
    } 
} 

/** 
* Cast a CheckedException as an unchecked one. 
* 
* @param throwable to cast 
* @param <T>  the type of the Throwable 
* @return this method will never return a Throwable instance, it will just throw it. 
* @throws T the throwable as an unchecked throwable 
*/ 
@SuppressWarnings("unchecked") 
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T { 
    throw (T) throwable; // rely on vacuous cast 
} 
+0

如果您想將檢查的異常轉換爲運行時異常,將需要添加另一個catch子句以獲得代碼編譯... –

0

有一種模式我已經看過幾次來處理這種情況。你讓handleException方法聲明它返回一個異常。這只是指示性的,但它永遠不會返回任何東西,它總是會拋出,就像以前一樣。聲明的返回類型將允許調用者使用throw handleException()語句,這將使編譯器保持高興。由此產生的代碼將爲:

public String getXYZ(String input) throws Exception { 
    try { 
     return getFromDAO(input); 
    } catch (Exception e) { 
     throw handleException(e); 
    } 
} 

/** 
* This method will never return normally, always throws. 
*/ 
private Exception handleException(Exception e) throws Exception 
{ 
    try { 
     throw e; 
    } catch(SomeException se) { 
     throw new MyRuntimeException("MyException message", se); 
    } catch(SomeOtherException soe) { 
     throw new MyRuntimeException("MyException message", soe); 
    } 
} 
1

您可能還想考慮使用新的java 8 lambda功能來解決您的問題。您必須創建一個函數接口來聲明lambda表達式的簽名(以及相關的例外)。您的handleException方法現在將成爲運行lambda並處理異常的人。

public String getXYZ(String input) { 
    return handleKnownExceptions(() -> getFromDAO(input)); 
} 

private <T> T handleKnownExceptions(ThrowingCode<T> throwingCode) 
{ 
    try { 
     return throwingCode.get(); 
    } catch(SomeException se) { 
     throw new MyRuntimeException("MyException message", se); 
    } catch(SomeOtherException soe) { 
     throw new MyRuntimeException("MyException message", soe); 
    } 
} 

@FunctionalInterface 
public interface ThrowingCode<T> 
{ 
    T get() throws SomeException, SomeOtherException; 
}