当我们需要抛出自定义异常时,如何防止异常捕获?

时间:2018-07-26 16:12:29

标签: java exception exception-handling

  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抛出异常,它将再次被捕获,从而导致重复记录。如果我只想登录bar message,我不想打印foo message

如何防止它发生?

4 个答案:

答案 0 :(得分:3)

response语句之后验证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");
}

我不建议捕获Exception-太笼统了,我建议您将其范围缩小到更具体的异常类型。

答案 1 :(得分:1)

如果将其移到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");
}

答案 2 :(得分:0)

创建自己的异常类型,不要捕获它。

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

答案 3 :(得分:0)

首先,让我指出您的代码中的错误。您的方法声明它抛出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()引发异常,它甚至不会到达该行。