1

请看下面的DbUtil类示例。以下是它的三种方法

public static void closeResults(ResultSet rs) {
    if (rs != null) {
        try {
            if (!rs.isClosed()){
                rs.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

public static void closeStatement(Statement stmt) {
    if(stmt != null) {
        try {
            if (!stmt.isClosed()) {
                stmt.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

public static void closeConnection(Connection conn) {
    if(conn != null) {
        try {
            if(!conn.isClosed()) {
                conn.close();    
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

如您所见,所有 3 种方法都有相同的逻辑,我想让这段代码干燥。一个新的常用方法可以这样写

public static void closeStatement(AutoCloseable ob) {
    if(ob != null) {
        try {
            ob.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

AutoCloseable接口不包含isClosed方法。但是在尝试关闭资源之前执行该检查仍然是一个好习惯(甚至必须做)。我对吗?代码可以以某种方式简化并且仍然执行isClosed检查吗?

笔记。这只是问题的一个例子。我知道该AutoCloseable界面是为尝试资源技术而设计的,因此可以使用该样式重写代码,并且DbUtil不再需要。但我想为自己澄清一下,在类似的情况下甚至可以做些什么。例如,我会考虑创建一些接口,例如,MyAutoCloseable扩展AutoCloseable一个并拥有isClosed方法,但肯定不会奏效,因为不可能强制转换ResultSetStatement转换为MyAutoCloseable.

4

2 回答 2

1

你根本不需要打电话isClosed()close()20 年来我在 JDK 中见过的每一种方法都是幂等的,这意味着你可以调用它两次或更多次而不会造成伤害。

于 2017-07-14T10:18:53.100 回答
0

您可以使用反射来实现它。

public static void close(Object obj)
{
    try
    {
        Class<?> c = obj.getClass();
        Method isClosed = c.getDeclaredMethod("isClosed");// No I18N
        if( (Boolean)isClosed.invoke(obj) )
        {
            Method close = c.getDeclaredMethod("close");
            close.invoke(obj);
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}
于 2017-07-14T09:59:27.440 回答