[英]Java - Handle multiple exceptions in method
我正在開發一個公共API供人們在他們的應用程序中使用。 我目前正試圖找出處理異常的最佳方法。 例如,以下代碼段會拋出四種不同的異常:
Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
s.initSign(keyChain.getPrivateKey()); //InvalidKeyException
s.update(plainText.getBytes("UTF-8")); //UnsupportedEncodingException
byte[] signature = s.sign(); //SignatureException
String signedData = base64Encoder.encode(signature);
我的問題是,我該如何以最佳方式處理這些問題?
我提出的一種方法是捕獲異常並拋出自定義異常:
public void signRequest(Request request) throws APISignatureException {
try {
...
Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
s.initSign(keyChain.getPrivateKey()); //InvalidKeyException
s.update(plainText.getBytes("UTF-8")); //UnsupportedEncodingException
byte[] signature = s.sign(); //SignatureException
String signedData = base64Encoder.encode(signature);
...
}
catch (Exception e) {
throw new APISignatureException("Failed to create signature", e);
}
}
這是處理開放API異常的好方法嗎?
這幾乎是一種合理的方式! 我要說的是,如果你用一系列特定的例外代替你的catch
,而不是一攬子的Exception
,它將是完全可以防御的。
但是,讓所有四種類型向上傳播也是非常合理的。 這取決於你想要什么。 如果用戶想要立即訪問失敗的原因,您可以保留未更改和未捕獲的類型。 如果你想要這個抽象層,用戶只是得到一個“簽名”類型出錯的東西,但仍然可以深入細節,那么你得到的結構是理想的。
關鍵是你沒有隱藏任何東西:原始異常仍然埋沒在新異常中,並且可供調用者使用。
捕捉一般例外通常是一個壞主意。
你可以這樣做(Java 7):
public void signRequest(Request request) throws APISignatureException {
try {
Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
s.initSign(keyChain.getPrivateKey()); //InvalidKeyException
s.update(plainText.getBytes("UTF-8")); //UnsupportedEncodingException
byte[] signature = s.sign(); //SignatureException
String signedData = base64Encoder.encode(signature);
}
catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException | SignatureException e) {
throw new APISignatureException("Failed to create signature", e);
}
}
但問問自己客戶將要做什么,因為你迫使他仍然抓住你的例外。
如果客戶端不應該擔心,因為一般情況下這不會出錯,你可以拋出一個未經檢查的異常:
public void signRequest(Request request) {
try {
Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
s.initSign(keyChain.getPrivateKey()); //InvalidKeyException
s.update(plainText.getBytes("UTF-8")); //UnsupportedEncodingException
byte[] signature = s.sign(); //SignatureException
String signedData = base64Encoder.encode(signature);
}
catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException | SignatureException e) {
throw new RuntimeException("Failed to create signature", e); // This doesn't need to be explicitly caught
}
}
我的意思是,如果簽名出錯,用戶可能不需要繼續他的應用程序,就好像通過捕獲自己的異常一樣沒有發生任何事情。 他需要更改一些配置並再次運行他的應用程序。 RuntimeException
將只傳播,直到更一般的捕獲器捕獲它。
處理異常取決於您想要做什么。 大多數情況下,您無法在當前方法中執行任何操作,並且只能將錯誤傳遞給調用方法,然后您可以包裝並重新拋出(甚至在您自己的簽名中聲明異常)。 但有一段時間你可以處理它。 例如,如果找不到並打開屬性文件,則可以使用默認值。
這是我個人的意見
我會說你對用戶的例外越多,他可以發展的錯誤越詳細。 由於這是一個開放的API,意味着每個人都可以使用它,我會尋求粒度並提供錯誤,以幫助用戶找出問題所在。
如果您在每個例外中提供一個特定錯誤,則用戶也可以作為開發人員向您提供反饋。 他正在嘗試你的api並得到一個錯誤,他會告訴你git你提供給他的一個例外,然后你必須弄清楚出了什么問題。
如果您使用Java 7,那么您可以在同一個catch子句中捕獲多個異常,
catch (APISignatureException|SignatureException e) {
throw e;
}
否則你需要單獨捕捉它們
catch (APISignatureException e) {
throw e;
}
catch (SignatureException e) {
throw e;
}
您不應該使用Exception
的超類型,因此您最終不會捕獲您不想處理的異常
現在所有的異常都被catch(Exception e)捕獲{然后它們都會拋出一個APISignatureException 。
你真正想要做的是抓住你的特定異常,如下所示:
public void signRequest(Request request) throws APISignatureException {
try {
...
Signature s = Signature.getInstance("SHA1withRSA"); //NoSuchAlgorithmException
s.initSign(keyChain.getPrivateKey()); //InvalidKeyException
s.update(plainText.getBytes("UTF-8")); //UnsupportedEncodingException
byte[] signature = s.sign(); //SignatureException
String signedData = base64Encoder.encode(signature);
...
}
catch (APISignatureException e) {
//Handle exception
}
catch (InvalidKeyException e) {
//Handle exception
}
此外,如果您捕獲特定的異常,則無需拋出另一個異常。
您還可以組合捕獲多個異常,如下所示:
catch (APISignatureException|InvalidKeyException e) {
// Handle exception
}
您可以通過擴展Exception類來創建自定義異常:
class APISignatureException extends Exception {
// empty constructor
public APISignatureException () {}
//constructor that takes a string message
public APISignatureException (String message)
{
super(message);
}
}
有關更多詳細信息,請查看異常
你需要了解這一點,請仔細研究。
基本的理解是
try {
//Something that can throw an exception.
} catch (Exception e) {
// To do whatever when the exception is caught.
}
還有一個finally塊,即使出現錯誤也始終執行。 它像這樣使用
try {
//Something that can throw an exception.
} catch (Exception e) {
// To do whatever when the exception is caught & the returned.
} finally {
// This will always execute if there is an exception or no exception.
}
在掃描儀的特定情況下,您可以有以下例外( 鏈接 )。
InputMismatchException - 如果下一個標記與Integer正則表達式不匹配,或者超出范圍
NoSuchElementException - 如果輸入用盡
IllegalStateException - 如果此掃描程序已關閉
所以你需要捕獲像這樣的例外
try {
rows=scan.nextInt();
} catch (InputMismatchException e) {
// When the InputMismatchException is caught.
System.out.println("The next token does not match the Integer regular expression, or is out of range");
} catch (NoSuchElementException e) {
// When the NoSuchElementException is caught.
System.out.println("Input is exhausted");
} catch (IllegalStateException e) {
// When the IllegalStateException is caught.
System.out.println("Scanner is close");
}
當我編寫API時,我會捕獲較低級別的異常並拋出相關的API異常。 這樣您就不會隱藏任何內容,並允許API用戶捕獲一個相關的異常。
如果API很大,您可能需要幾個API異常,它們都是常見API異常的子類。 例如:
public class APIException { ...
}
public class APISignatureException extends APIException { ...
}
public class APISomeException extends APIException { ...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.