簡體   English   中英

Java - 處理方法中的多個異常

[英]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你提供給他的一個例外,然后你必須弄清楚出了什么問題。

Gief所有的信息

如果您使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM