这是我们写的一段代码:
public CustomerTO getCustomerByCustDel(final String cust, final int del) throws SQLException { final PreparedStatement query = getFetchByCustDel(); ResultSet records = null; try { query.setString(1, cust); query.setInt(2, del); records = query.executeQuery(); return this.getCustomer(records); } finally { if (records != null) { records.close(); } query.close(); } }
如果省略'finally'块,则会使数据库资源悬空,这显然是一个潜在的问题。但是,如果您执行我在此处所做的操作 - 在** try **块之外将ResultSet设置为null,然后将其设置为块内所需的值 - PMD报告'DD异常'。在文档中,DD异常描述如下:
DataflowAnomalyAnalysis:数据流分析跟踪数据流上不同路径上的变量的本地定义,未定义和引用。从这些信息中可以发现各种问题。 [...] DD - 异常:重新定义了最近定义的变量。这是不祥的,但不一定是一个错误。
如果在块外部声明ResultSet而不设置值,则在执行 if(records!= null)测试时,正确地得到'变量可能未初始化'错误。< / p>
现在,在我看来,我在这里使用不是一个错误。但有没有一种干净的重写方式,不会触发PMD警告?我并不特别想要禁用PMD的DataFlowAnomalyAnalysis规则,因为识别UR和DU异常实际上是有用的;但是这些DD异常让我怀疑自己可以做得更好 - 而且,如果没有更好的方法可以做到这一点,那么它们就会变得混乱(我应该看看是否可以重写PMD规则)
答案 0 :(得分: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()抛出异常,则查询不会被关闭。
答案 1 :(得分:1)
我认为DD异常注释比一个特征更多的bug 此外,释放资源的方式有点不完整,例如
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) {
}
}
}