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