6

这是我们都编写的一段代码:

    public CustomerTO getCustomerByCustDel(final String cust, final int del)
            抛出 SQLException {
        最终 PreparedStatement 查询 = getFetchByCustDel();
        结果集记录=空;
        尝试 {
            query.setString(1, cust);
            query.setInt(2, del);
            记录 = query.executeQuery();

            返回 this.getCustomer(records);
        } 最后 {
            如果(记录!= null){
                记录.close();
            }
            查询.close();
        }
    }

如果省略“finally”块,那么数据库资源就会悬空,这显然是一个潜在问题。但是,如果您按照我在此处所做的操作 - 在 **try** 块外将 ResultSet 设置为 null,然后在块内将其设置为所需的值 - PMD 会报告“DD 异常”。在文档中,DD 异常描述如下:

DataflowAnomalyAnalysis:数据流分析跟踪本地定义、未定义和对数据流不同路径上变量的引用。从这些信息中可以发现各种问题。[...] DD - 异常:重新定义了最近定义的变量。这是不祥之兆,但不一定是错误。

如果您在块外声明 ResultSet 而不设置值,则在执行if (records != null)测试时,您会正确地得到“变量可能尚未初始化”错误。

现在,在我看来,我在这里的使用不是错误。但是有没有一种干净地重写不会触发 PMD 警告的方法?我不是特别想禁用 PMD 的 DataFlowAnomalyAnalysis 规则,因为识别 UR 和 DU 异常实际上很有用;但是这些 DD 异常让我怀疑我可以做得更好——而且,如果没有更好的方法来做到这一点,它们就会变得混乱(我也许应该看看我是否可以重写 PMD 规则)

4

2 回答 2

2

我认为这更清楚:

PreparedStatement query = getFetchByCustDel();
try {
    query.setString(1, cust);
    query.setInt(2, del);
    ResultSet records = query.executeQuery();
    try {
        return this.getCustomer(records);
    } finally {
        records.close();
    }
} finally {
    query.close();
}

此外,在您的版本中,如果 records.close() 抛出异常,查询不会关闭。

于 2012-05-25T23:26:36.413 回答
1

我认为 DD 异常注释更多的是错误,而不是功能
另外,您释放资源的方式有点不完整,例如

PreparedStatement pstmt = null;
Statement st = null; 

try {
    ...
} catch (final Exception e) {
    ...
} finally {
    try{
        if (pstmt != null) {
            pstmt.close();
        }
    } catch (final Exception e) {
        e.printStackTrace(System.err);
    } finally {
        try {
            if (st != null) {
                st.close();
            }
        } catch (final Exception e) {
            e.printStackTrace(System.err);
        }
    }
}

而且这又不对了,因为你应该关闭这样的资源

PreparedStatement pstmt = null;
Throwable th = null;

try {
    ...
} catch (final Throwable e) {
    <something here>
    th = e;
    throw e;
} finally {
    if (th == null) {
        pstmt.close();
    } else {
        try {
            if (pstmt != null) {
                pstmt.close();
            }
        } catch (Throwable u) {
        }
    }
}
于 2013-09-25T06:56:43.440 回答