【问题标题】:Try-catch-finally and then again a try catchTry-catch-finally 然后再次尝试捕获
【发布时间】:2010-11-23 01:50:49
【问题描述】:

我经常遇到这样的情况:-

try{ 
     ...
     stmts
     ...
} 
catch(Exception ex) {
     ... 
     stmts
     ... 
} finally {
     connection.close // throws an exception
}

finally 内部仍然需要一个 try-catch 块。

克服这个问题的最佳做法是什么?

【问题讨论】:

  • 你可能会发现资源获取也抛出了。 (所以真的使用赛斯的答案。)

标签: java exception-handling try-catch-finally


【解决方案1】:

我通常是这样做的:

try {
    try {
        ..
        stmts
        ...
    }
    finally {
       connection.close():
    }
} catch (Exception ex) {
     ..
     stmts
     ..    
}

我通常只在不使用为我处理此管道的库时才使用它。

正如Imagist 指出的那样,这在技术上与 finally 将在 catch 之前运行不同,但我认为它解决了您试图解决的问题。

【讨论】:

  • 这在技术上并不相同,但根据具体情况,它可能会按照 Ajay 的意愿行事。
  • 你当然可以用 Execute Around 成语抽象出来。
  • @tackline:谢谢!以前没见过。这里有一个链接供其他感兴趣的人使用:stackoverflow.com/questions/341971/…
  • 这种方法的问题是,通常你不想对与关闭相关的异常做同样的事情,就像你对方法主体中的异常做的那样——更糟糕的是,这段代码如果 finally 抛出异常,将在主体中吞下异常。
【解决方案2】:

编写一个SQLUtils 类,其中包含捕获和记录此类异常的static closeQuietly 方法,然后酌情使用。

你最终会得到如下内容:

public class SQLUtils 
{
  private static Log log = LogFactory.getLog(SQLUtils.class);

  public static void closeQuietly(Connection connection)
  {
    try
    {
      if (connection != null)
      {
        connection.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing connection.", e);
    }
  }

  public static void closeQuietly(Statement statement)
  {
    try
    {
      if (statement!= null)
      {
        statement.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing statement.", e);
    }
  }

  public static void closeQuietly(ResultSet resultSet)
  {
    try
    {
      if (resultSet!= null)
      {
        resultSet.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing result set.", e);
    }
  }
}

您的客户端代码将类似于:

Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try 
{
  connection = getConnection();
  statement = connection.prepareStatement(...);
  resultSet = statement.executeQuery();

  ...
}
finally
{
  SQLUtils.closeQuietly(resultSet);
  SQLUtils.closeQuietly(statment);
  SQLUtils.closeQuietly(connection);
}

更新: 从 Java 7 开始,各种 JDBC 接口扩展了 java.lang.AutoCloseable,虽然上面的代码回答了最初的问题,但如果您直接针对 JDBC API 编写代码,现在可以结构化:

try (
  Connection connection = getConnection();
  PreparedStatement statement = connection.prepareStatement(...);
  ResultSet resultSet = statement.executeQuery()
)
{
  ...
}

【讨论】:

  • 这也是我过去的选择,但我最近发现有一些类,比如 apache commons DBUtil,可以为你做这件事。
【解决方案3】:

不要犹豫,再试一次……终于抓住了。

【讨论】:

    【解决方案4】:

    记住 .. finally 总是使用 try 或 catch 执行 ..

    【讨论】:

      【解决方案5】:

      通常,除了记录关闭资源时发生的异常之外,您不想做任何事情,因此它应该真正进入自己的 try/catch 中。但是,这是经常发生的通用代码,所以不要重复自己,并将关闭放在静态方法中(如 Nick Holt 建议的那样),这样您就不会在同一方法中使用两个 try/catch 项,使代码更易于阅读和遵循。

      【讨论】:

      • 我不确定我是否同意这一点。在我看来,关闭资源失败代表了比使用过程中发生的典型异常更严重的问题。应该努力保持内部异常(在 vb.net 中比 C# 更容易)但抛出“更严重”的异常。
      • 如果你是从网络上读取并且你已经完成了,资源关闭失败真的有什么后果吗?它当然不会改变程序的任何内容。
      • 除非它使端口开放且对其他人无法使用
      【解决方案6】:

      Commons-io 也有 closeQuietly() 用于输入和输出流。我一直在使用它。它使您的代码更具可读性。

      【讨论】:

        【解决方案7】:

        正如其他人所提到的,静态closeQuietly 实用程序是要走的路。要补充的一件事 - 如果你在 java.io 而不是 java.sql 的世界中,那么有一个有用的界面可以用于此目的 - java.io.Closeable

        java.io 中的所有数据源和接收器都实现了这个接口——所有流、通道、写入器和读取器。这样,您可以创建一个实用程序来处理相同的“close() 异常”问题,而无需许多重载版本。

        例如

        public class IoUtils {
        
          public static closeQuietly (Closeable closeable) {
            try {
              closeable.close();
            } catch (IOException logAndContinue) {
              ...
            }
          }
        
        }
        

        【讨论】:

          【解决方案8】:

          Google Guava 库中还有方便的 Closeables#closeQuitely 方法 - 它可以用于任何 Closeable

          【讨论】:

            【解决方案9】:

            我们可以在 try 块之后加上 finally bock 和 catch 块吗?

            【讨论】:

              【解决方案10】:

              在 Java 10 中,您可以编写:

              public void java10() throws SQLException {
                  try (var connection = Connections.openConnection();
                       var callableStatement = connection.prepareCall("my_call");
                       var resultSet = callableStatement.executeQuery()) {
              
                      while (resultSet.next()) {
                          var value = resultSet.getString(1);
                          System.out.println(value);
                      }
                  }
              }
              

              在 Java 7、8 和 9 中,您可以编写:

              public void java7() throws SQLException {
                  try (Connection connection = Connections.openConnection();
                       CallableStatement callableStatement = connection.prepareCall("my_call");
                       ResultSet resultSet = callableStatement.executeQuery()) {
              
                      while (resultSet.next()) {
                          String value = resultSet.getString(1);
                          System.out.println(value);
                      }
                  }
              }
              

              在 Java 6 中,您需要编写所有这些行:

              public void java6() throws SQLException {
                  Connection connection = Connections.openConnection();
                  try {
                      CallableStatement callableStatement = connection.prepareCall("my_call");
                      try {
                          ResultSet resultSet = callableStatement.executeQuery();
                          try {
                              while (resultSet.next()) {
                                  String value = resultSet.getString(1);
                                  System.out.println(value);
                              }
                          } finally {
                              try {
                                  resultSet.close();
                              } catch (Exception ignored) {
                              }
                          }
                      } finally {
                          try {
                              callableStatement.close();
                          } catch (Exception ignored) {
                          }
                      }
                  } finally {
                      try {
                          connection.close();
                      } catch (Exception ignored) {
                      }
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2014-04-27
                • 2010-09-12
                • 1970-01-01
                • 2014-11-27
                • 1970-01-01
                • 1970-01-01
                • 2016-08-22
                • 1970-01-01
                相关资源
                最近更新 更多