Java 来自PMD的数据流异常分析警告

Java 来自PMD的数据流异常分析警告,java,pmd,dataflow,anomaly-detection,Java,Pmd,Dataflow,Anomaly Detection,我将Eclipse与PMD插件一起使用(4.0.0.v20130510-1000),并且得到了很多违规行为: 发现变量“freq”(行“187”-“189”)的“DD”-异常。 发现变量“freq”(行“189”-“333”)的“DU”异常。 在答案中,它说这些异常与分配从未读取的值有关。但我得到了一些违规行为,比如在这个案例中: // here I get a DD anomaly double freq = 0; try { // here I get a DU anomaly fr

我将Eclipse与PMD插件一起使用(4.0.0.v20130510-1000),并且得到了很多违规行为:

发现变量“freq”(行“187”-“189”)的“DD”-异常。

发现变量“freq”(行“189”-“333”)的“DU”异常。

在答案中,它说这些异常与分配从未读取的值有关。但我得到了一些违规行为,比如在这个案例中:

// here I get a DD anomaly
double freq = 0;
try {
  // here I get a DU anomaly
  freq = Double.parseDouble(getFrequencyTextField().getText());
} catch (final NumberFormatException e) {
  Log.e(e.getMessage());
}
if (freq < 10E6) doSomething();
//这里有一个DD异常
双频=0;
试一试{
//这里有一个DU异常
freq=Double.parseDouble(getFrequencyTextField().getText());
}捕获(最终编号格式e){
Log.e(e.getMessage());
}
如果(频率<10E6)剂量测量();
如果我删除初始化并添加
freq=0行在
catch
块中,DD异常消失,但我在两个赋值上都得到DU异常


现在我的问题是:我该怎么处理?PMD的首选解决方案是什么?这条规则到底想防止什么(即为什么这是一种不好的做法)?

您可以通过将解析提取到一个单独的方法来绕过这个问题(更清楚地分离关注点):

double freq = parseDouble(getFrequencyTextField().getText());

// later in the class (or in a utility class):

public static double parseDouble(final String input) {
  try {
    return Double.parseDouble(input);
  } catch (final NumberFormatException e) {
    Log.e(e.getMessage());
    return 0;
  }
}
如果您有不同的默认值,还可以添加一个双参数版本:
publicstaticdouble-parseDouble(最终字符串输入,最终双默认值)

double-freq;//(1)
试一试{
//这里有一个DU异常
freq=Double.parseDouble(getFrequencyTextField().getText());
}捕获(最终编号格式e){
Log.e(e.getMessage());
频率=0;//(2)
}
如果(频率<10E6)剂量测量();
第一个问题是在catch中没有对freq执行parseDouble赋值。 在异常情况下,freq仍然为0。也许是可悬挂的。 因此,当分配给freq inside catch时,它消失了

当在catch(2)中赋值给freq时,初始赋值(1)永远不会被读取,因此只有一个声明就足够了

关于更好的风格:

try {
  // here I get a DU anomaly
  double freq = Double.parseDouble(getFrequencyTextField().getText());

  if (freq < 10E6) doSomething();
  ...

} catch (final NumberFormatException e) {
  Log.e(e.getMessage());
}
试试看{
//这里有一个DU异常
double freq=double.parseDouble(getFrequencyTextField().getText());
如果(频率<10E6)剂量测量();
...
}捕获(最终编号格式e){
Log.e(e.getMessage());
}

或者按照@JoachimSauer的答案,使用不会引发异常的双重转换。日志记录将显示优先于上述样式的严重程度。在一个简单的转换函数中记录错误可能不是一种好的方式:记录太多,忽略记录(?),很难修复。

我喜欢默认值的想法。我想我会这么做的。虽然在那个例子中,我只是得到了下一个PMD冲突:
一个方法应该只有一个退出点,这应该是方法中的最后一个语句
@brimborium:这个警告创建了一个丑陋的语义循环:我看不到(简单的)解决方案可以同时避免两个警告。是的,我倾向于把第二条规则从规则集中踢出去。虽然我理解这一点。如果只有一个出口点,那么理解复杂方法的全部含义就容易多了……就我个人而言,我根本不同意一个出口点规则。它常常使代码变得不必要的复杂。我想用“在意外的地方没有出口点”规则来代替它,但这可能会稍微难以检查静态分析器;-)挡块中的回位总是不好的。添加一个finally块,你就有了混乱的代码。谢谢你的解释,这为我澄清了问题。也谢谢你的建议。我总是喜欢代码风格的更正。(这就是我开始使用PMD的原因。)
try {
  // here I get a DU anomaly
  double freq = Double.parseDouble(getFrequencyTextField().getText());

  if (freq < 10E6) doSomething();
  ...

} catch (final NumberFormatException e) {
  Log.e(e.getMessage());
}