繁体   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