簡體   English   中英

當我們需要拋出自定義異常時,如何防止異常捕獲?

[英]How to prevent exception catching when we need to throw custom exceptions?

  void connectOverNetwork() throws Exception {
    try {
      final JSONObject response = make network call;

      if (!response.getBoolean(SUCCESS)) {
        LOG.error("--- foo message ---");
        throw new Exception("message replied with error");
      }
    } catch (final Exception e) {
      LOG.error("---- bar message ---");
      throw new SvcException("failed to connect over network");
    }
  }

在上面的代碼中,我拋出了帶有失敗消息的異常。 同時,由於無法通過網絡連接,我也會引發錯誤。

但是,如果我為!success拋出異常,它將再次被捕獲,從而導致重復記錄。 如果我只想記錄foo message ,我不想打印bar message foo message

如何防止它發生?

try-catch語句之后驗證response

JSONObject response = null;
try {
    response = /* make network call */;
} catch (final Exception e) {
    LOG.error("---- bar message ---");
    throw new SvcException("failed to connect over network");
}

if (!response.getBoolean(SUCCESS)) {
    LOG.error("--- foo message ---");
    throw new Exception("message replied with error");
}

我不建議捕獲Exception這太籠統了,建議您將其范圍縮小到更具體的異常類型。

如果將其移到try塊之外,該怎么辦。無論如何,第一次try..catch的原因是從網絡調用中捕獲任何異常。

JSONObject response = null;
try {
    response = make network call;
} catch (final Exception e) {
    LOG.error("---- bar message ---");
    throw new SvcException("failed to connect over network");
}
if (!response.getBoolean(SUCCESS)) {
    LOG.error("--- foo message ---");
    throw new Exception("message replied with error");
}

創建自己的異常類型,不要捕獲它。

try {
    do stuff
    if (condition) 
        throw new MyCustomException("error")
} catch (IOException e) {
    log and rethrow
}

首先,讓我指出您的代碼中的錯誤。 您的方法聲明它拋出Exception,但沒有。 它引發SvcException。 這就是“ throws”子句應該說的。 (無論如何,您永遠都不要說“引發異常”。您應該明確說明它引發的異常類型。)其余的答案取決於您模糊的描述“進行網絡呼叫”是否引發異常。

如果不是,則您的方法應如下所示:

void connectOverNetwork() throws SvcException {
  final JSONObject response = makeNetworkCall();

  if (!response.getBoolean(SUCCESS)) {
    LOG.error("--- foo message ---");
    throw new SvcException("message replied with error");
  }
}

但這是不現實的。 您的“進行網絡調用”代碼可能會拋出類似IOException的錯誤。 在這種情況下,您的代碼應如下所示:

void connectOverNetwork() throws SvcException {
  try {
    final JSONObject response = makeNetworkCall(); // throws IOException

    if (!response.getBoolean(SUCCESS)) {
      LOG.error("--- foo message ---");
      throw new SvcException("message replied with error");
    }
  } catch (final IOException e) {
    LOG.error("--- foo message ---");
    throw new SvcException("failed to connect", e); // wrap e inside SvcException
  }
}

請注意,我將捕獲的IOException包裝在SvcException中。 如果您的SvcException不這樣做,請重寫它以便可以,或者在拋出它之前調用其initCause()方法。 重新拋出其他異常時,應始終包含原始異常。

還要注意,我不用麻煩拋出,而是捕獲並重新拋出IOException。 當我檢測到故障時。 我只是拋出需要拋出的異常。 這意味着我需要在兩個不同的地方記錄foo消息。 對於大多數情況,應該避免重復執行一行代碼,但是對於日志記錄來說,這很好。

但是這段代碼有點混亂。 我將成功測試與可能的IOException分離開來進行清理。 所以我會這樣寫:

void connectOverNetwork() throws SvcException {
  JSONObject response; // no need to initialize this.
  try {
    response = makeNetworkCall(); // throws IOException
  } catch (final IOException e) {
    LOG.error("--- foo message ---");
    throw new SvcException("failed to connect", e); // wrap e inside SvcException
  }

  if (!response.getBoolean(SUCCESS)) {
    LOG.error("--- foo message ---");
    throw new SvcException("message replied with error");
  }
}

請注意,此處的響應是在try循環之前聲明的。 它沒有被初始化,因為沒有值就無法達到!response.getBoolean(SUCCESS)測試。 如果makeNetworkCall()引發異常,它甚至不會到達該行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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