代码之家  ›  专栏  ›  技术社区  ›  Tanvi Jaywant

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

  •  1
  • Tanvi Jaywant  · 技术社区  · 6 年前
      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 回复  |  直到 6 年前
        1
  •  3
  •   Andrew    6 年前

    验证 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 -这太一般了,我建议您将其缩小到更具体的异常类型。

        2
  •  1
  •   Thiyagu    6 年前

    如果你把它移到外面 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");
    }
    
        3
  •  0
  •   killjoy    6 年前

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

    try {
        do stuff
        if (condition) 
            throw new MyCustomException("error")
    } catch (IOException e) {
        log and rethrow
    }
    
        4
  •  0
  •   MiguelMunoz    6 年前

    首先,让我指出你代码中的一个错误。您的方法声明它抛出异常,但它没有。它抛出svception。所以这就是“抛出”条款应该说的。(无论如何,你不应该说“抛出异常”。你应该明确说明它抛出了什么类型的异常。)剩下的答案取决于你含糊不清的描述“make network call”是否抛出了异常。

    如果没有,您的方法应该如下所示:

    void connectOverNetwork() throws SvcException {
      final JSONObject response = makeNetworkCall();
    
      if (!response.getBoolean(SUCCESS)) {
        LOG.error("--- foo message ---");
        throw new SvcException("message replied with error");
      }
    }
    

    但这是不现实的。很可能,你的“make network call”代码抛出了类似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包装在svception中。如果svception没有这样做,请重写它以便它可以,或者调用它 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()抛出异常,它甚至不会到达该行。