【问题标题】:How to avoid throw clause in finally block如何避免 finally 块中的 throw 子句
【发布时间】:2015-01-28 08:01:37
【问题描述】:

我使用 SonarQube 来提高代码质量。我遇到了一个与异常处理相关的问题,即从 finally 块中删除 throw 子句。

} catch(Exception e) {
            throw new MyException("request failed : ", e);
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {               
                throw new MyException("failed to close server conn: ", e);
            }
        }

根据我的理解,上面的代码看起来不错。如果我在 finally 中删除 throw 子句并抑制异常,则此方法的调用者将无法知道服务器的状态。我不确定我们如何在没有 throw 子句的情况下实现相同的功能。

【问题讨论】:

  • 您是否尝试在内部 try-catch 块中添加 finally 块并查看它是否仍然发出警告?
  • 如果您已经在使用 throw 子句来指示同一函数中的其他错误,那么在这种特殊情况下使用不同的方法可能是不明智的?
  • 哦,我想你很担心,因为即使从未成功建立连接,你的finally 块仍然会抛出你的MyException,对吗?
  • @MarkoTopolnik,想提供一个描述什么是“try-with-resources 块”的链接吗?
  • @SebastianTroy 是的,你是对的。

标签: java


【解决方案1】:

您最好的方法是使用 Java 的 Automatic Resource Management 功能,该功能自 Java 7 起可用。如果由于某种原因您无法使用该功能,那么下一个最佳方法是复制该语法糖扩展的内容:

public static void runWithoutMasking() throws MyException {
   AutoClose autoClose = new AutoClose();
   MyException myException = null;
   try {
       autoClose.work();
   } catch (MyException e) {
       myException = e;
       throw e;
   } finally {
       if (myException != null) {
           try {
               autoClose.close();
           } catch (Throwable t) {
               myException.addSuppressed(t);
           }
       } else {
           autoClose.close();
       }
   }
}

注意事项:

  • 如果关闭资源失败,您的代码会从try 块中吞下原始异常。原始异常对于诊断肯定更重要;
  • 在上面的 ARM 习惯用法中,关闭资源的方式不同,具体取决于 try 块中是否已经存在异常。如果try 正常完成,则资源在任何try-catch 块之外关闭,自然会传播任何异常。

【讨论】:

    【解决方案2】:

    通常,finally 块中的方法是“清理”代码(关闭Connection 等),用户不一定需要知道。

    我对这些异常所做的是吸收异常,但记录详细信息。

    finally{
       try{
          connection.close();
       }catch(SQLException e){
          // do nothing and just log the error
          LOG.error("Something happened while closing connection. Cause: " + e.getMessage());
       }
    }
    

    【讨论】:

      【解决方案3】:

      您收到警告是因为此代码在处理抛出的异常时可能会抛出异常。您可以使用 try with resource 语法自动关闭资源。 Read more here.

      如果“请求失败:”异常被抛出并且您未能关闭httpclient,则第二个异常是会冒泡的异常。

      【讨论】:

        【解决方案4】:

        我不确定我们如何在不使用的情况下实现相同的功能 throw 子句。

        您可以不同地嵌套两个 try 块以获得相同的结果:

        HttpClient httpClient = null; // initialize
        try {
            try {
                // do something with httpClient
            } catch(Exception e) {
                throw new MyException("request failed : ", e);
            } finally {
                httpClient.close();
            }
        } catch (IOException e) {               
            throw new MyException("failed to close server conn: ", e);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-09-01
          • 2011-05-14
          • 1970-01-01
          • 1970-01-01
          • 2018-12-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多