FindBugs第1部分:提高代码质量

2008-04-09 03:57:07来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

使用 FindBugs 的原因和方法

级别: 中级

Chris Grindstaff
软件工程师, IBM
2004 年 5 月 25 日

静态分析工具承诺无需开发人员费劲就能找出代码中已有的缺陷。当然,如果有多年的编写经验,就会知道这些承诺并不是一定能兑现。尽管如此,好的静态分析工具仍然是工具箱中的无价之宝。在这个由两部分组成的系列文章的第一部分中,高级软件工程师 Chris Grindstaff 分析了 FindBugs 如何帮助提高代码质量以及排除隐含的缺陷。

代码质量工具的一个问题是它们容易为开发人员提供大量但并非真正问题的问题——即 伪问题(false positives)。出现伪问题时,开发人员要学会忽略工具的输出或者放弃它。FindBugs 的设计者 David Hovemeyer 和 William Pugh 注意到了这个问题,并努力减少他们所报告的伪问题数量。与其他静态分析工具不同,FindBugs 不注重样式或者格式,它试图只寻找真正的缺陷或者潜在的性能问题。

FindBugs是什么?
FindBugs 是一个静态分析工具,它检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。有了静态分析工具,就可以在不实际运行程序的情况对软件进行分析。不是通过分析类文件的形式或结构来确定程序的意图,而是通常使用 Visitor 模式。图 1 显示了分析一个匿名项目的结果(为防止可怕的犯罪,这里不给出它的名字):

让我们看几个 FindBugs 可以发现的问题。

问题发现的例子
下面的列表没有包括 FindBug 可以找到的 所有问题。相反,我侧重于一些更有意思的问题。

检测器:找出 hash equals 不匹配
这个检测器寻找与 equals()hashCode() 的实现相关的几个问题。这两个方法非常重要,因为几乎所有基于集合的类—— List、Map、Set 等都调用它们。一般来说,这个检测器寻找两种不同类型的问题——当一个类:

  • 重写对象的 equals() 方法,但是没有重写它的 hashCode 方法,或者相反的情况时。

  • 定义一个 co-variant 版本的 equals()compareTo() 方法。例如, Bob 类定义其 equals() 方法为布尔 equals(Bob) ,它覆盖了对象中定义的 equals() 方法。因为 Java 代码在编译时解析重载方法的方式,在运行时使用的几乎总是在对象中定义的这个版本的方法,而不是在 Bob 中定义的那一个(除非显式将 equals() 方法的参数强制转换为 Bob 类型)。因此,当这个类的一个实例放入到类集合中的任何一个中时,使用的是 Object.equals() 版本的方法,而不是在 Bob 中定义的版本。在这种情况下, Bob 类应当定义一个接受类型为 Object 的参数的 equals() 方法。

检测器:忽略方法返回值
这个检测器查找代码中忽略了不应该忽略的方法返回值的地方。这种情况的一个常见例子是在调用 String 方法时,如在清单 1 中:

忽略返回值的例子

1  String aString = "bob";
2  b.replace('b', 'p');
3  if(b.equals("pop"))

这个错误很常见。在第 2 行,程序员认为他已经用 p 替换了字符串中的所有 b。确实是这样,但是他忘记了字符串是不可变的。所有这类方法都返回一个新字符串,而从来不会改变消息的接收者。

检测器:Null 指针对 null 的解引用(dereference)和冗余比较
这个检测器查找两类问题。它查找代码路径将会或者可能造成 null 指针异常的情况,它还查找对 null 的冗余比较的情况。例如,如果两个比较值都为 null,那么它们就是冗余的并可能表明代码错误。FindBugs 在可以确定一个值为 null 而另一个值不为 null 时,检测类似的错误,如清单 2 所示:

Null 指针示例

1  Person person = aMap.get("bob");
2  if (person != null) {
3      person.updateAccessTime();
4  }
5  String name = person.getName();

在这个例子中,如果第 1 行的

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:概要设计说明书应包括的内容

下一篇:使用RationalSoftwareArchitect