[英]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.