Java 哪一种方法更好?嵌套try finally还是使用if条件进行一次尝试

Java 哪一种方法更好?嵌套try finally还是使用if条件进行一次尝试,java,jdbc,Java,Jdbc,对于使用JDBC在数据库中插入记录,有两种方法: 嵌套尝试。。最后:在这种方法中,嵌套的try和finally用于closeprepare语句和连接 public void performInsert(String insertSQL) { try { Connection connection = dataSource.getConnection(); try { PreparedStatement insertStmt = co

对于使用JDBC在数据库中插入记录,有两种方法:

  • 嵌套尝试。。最后:在这种方法中,嵌套的try和finally用于closeprepare语句和连接

    public void performInsert(String insertSQL) {
        try {
            Connection connection = dataSource.getConnection();
            try {
                PreparedStatement insertStmt = connection
                        .prepareStatement(insertSQL);
                try {
                    // bind value to prepare statements
                    insertStmt.executeUpdate();
                } finally {
                    insertStmt.close();
                }
            } finally {
                connection.close();
            }
        } catch (SQLException e) {
            // TODO: handle exception
        }
    }
    
  • 在finally块中使用if条件进行单次尝试:在这种方法中,close语句和连接的单次尝试使用和在finally块中使用if条件:

    public void performInsertIF(String insertSQL) {
        Connection connection = null;
        PreparedStatement insertStmt = null;
        try {
            connection = dataSource.getConnection();
            insertStmt = connection.prepareStatement(insertSQL);
            // bind value to prepare statements
            insertStmt.executeUpdate();
        }catch (SQLException e) {
            // TODO: handle exception
        } finally {
            if( insertStmt != null) {
                try {
                    insertStmt.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
    
            if( connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    

  • 上述两种方法都可以正常工作,但使用哪种方法更好,原因是什么?

    在上述代码中,两种方法都可以正常工作,但第二种方法在某种程度上更好,因为在调用
    close()
    对象之前先检查
    null
    对象。对空对象调用
    close()
    将抛出
    NullPointerException


    然而,在Java7+中,您可以使用更好的替代方法,称为。

    您应该使用第二种方法。 使用静态方法创建一个实用程序,这些方法使用空检查关闭资源

    public class DBUtils{
    public static void closeConnection(Connection  con){
        if(con != null){
               // close the connection
            }
        }
    }
    

    我通常使用与第二个示例非常相似的结构

    public void performInsertIF(String insertSQL) {
    Connection connection = null;
    PreparedStatement insertStmt = null;
    try {
        connection = dataSource.getConnection();
        insertStmt = connection.prepareStatement(insertSQL);
        // bind value to prepare statements
        insertStmt.executeUpdate();
    }
    catch (SQLException e) {
        // TODO: handle exception
    }
    finally {
    
        try {
            insertStmt.close();
        }
        catch(Exception ignore) {
        }
    
        try {
            connection.close();
        }
        catch(Exception ignore) {
        }
    }
    
    }

    但是,如果您真的想在finally块中打印SQLExceptions的stacktrace,我个人会使用这个变体,因为我认为它看起来更整洁/更干净

    public void performInsertIF(String insertSQL) {
    Connection connection = null;
    PreparedStatement insertStmt = null;
    try {
        connection = dataSource.getConnection();
        insertStmt = connection.prepareStatement(insertSQL);
        // bind value to prepare statements
        insertStmt.executeUpdate();
    }
    catch (SQLException e) {
        // TODO: handle exception
    }
    finally {
    
        try {
            insertStmt.close();
        }
        catch(NullPointerException ignore) {
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    
        try {
            connection.close();
        }
        catch(NullPointerException ignore) {
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    }最好的选择(假设Java 7或更高版本)是使用:


    try块结束后,
    connection
    insertStmt
    将自动关闭(与创建顺序相反)。如果语句prepare失败,
    连接
    甚至会关闭,或者
    insertStmt
    关闭失败。

    如果您有Java 7+,您可以使用try with resources作为更好的第三种选择:在第一种方法中,
    连接
    insertStmt
    关闭()时都不会为空
    被调用。@markrotVeel在上面的代码中两种方法都很好,这不是我的问题,你说“但是第二种方法更好……因为你检查一个空对象……对空对象调用close()将抛出一个NullPointerException”。这不适用于第一种方法,因为在显示的代码中调用
    close()
    时,
    connection
    insertStmt
    都不能
    null
    ,从而使您认为第二种方法更好的论点无效check@MarkRotteveel你没能理解我的论点。我的意思是,第二种方法通常更好。当我说第二种方法更好时,我并不是针对这个例子。我不同意——但这主要是一个品味问题——第一种方法更好(如果你不能使用try with resources,那就是)。它需要更少的检查(如空检查),但代价是额外的嵌套try-finally块。您根本无法捕获
    NullPointerException
    。一个
    NullPointerException
    简单地证明了代码有缺陷。就个人而言,我不会像使用第一个示例那样捕获NPE。不过,我不同意代码有缺陷,因为finally块中的两个对象可能不是由于前面代码的错误而为null。你误解了我的意思。我没说你的代码有问题。我说如果一个程序抛出一个NPE,它在大多数情况下是有缺陷的,并且没有适当的检查。因此,捕捉NPE是一种不好的做法。但是,当然,这取决于上下文。当然,在主流中捕获/吸收NPE是不好的做法,但我个人认为规则不应该应用于仅用于清理的finally块…特别是我们知道对象可能为null,如果为null,我们不感兴趣。如果con.close()抛出异常怎么办?如果您想捕获异常,你应该做第二种方式中提到的事情。在理想情况下使用此实用程序时,不应引发异常。
    public void performInsert(String insertSQL) {
        try (
            Connection connection = dataSource.getConnection();
            PreparedStatement insertStmt = connection
                        .prepareStatement(insertSQL);
        ) {
            // bind value to prepare statements
            insertStmt.executeUpdate();
        } catch (SQLException e) {
            // TODO: handle exception
        }
    }