【原创文章,转载请注明原文章地址,谢谢!】
一、什么是FindBugs
FindBugs 是一个静态分析工具,它检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题。它可以简单高效全面地帮助我们发现程序代码中存在的bug,bad smell,以及潜在隐患。针对各种问题,它并且提供了简单的修改意见供我们重构时进行参考; 通过使用它,可以一定程度上降低我们code review的工作量,并且会提高review效率。 通过findbugs找到bug,再由我们自己重构代码,可以培养我们的编码意识及水平,形成好的习惯提高开发编码能力
二、安装FindBugs
点击“Help->InstallNew Software”,如下图:
在Name中输入findBugs
, 在Location中输入:http://findbugs.cs.umd.edu/eclipse
三、 怎么使用
安装好插件后,选择指定的包或者类进行Find Bugs
打开Window-->Show View-->Bug Explore,就可以开到bug列表了.
找出的bug有3种颜色,
黑色的臭虫标志是分类。
红色的臭虫表示严重bug发现后必须修改代码。
橘黄的臭虫表示潜在警告性bug 尽量修改。
双击bug项目就可以在右边编辑窗口自动打开相关代码文件并连接到代码片段。 点击行号旁边的小臭虫图标后再eclipse下方输出区将提供详细的bug描述,以及修改建议等信息。我们可以根据此信息进行修改。
四、问题发现的例子
忽略方法返回值
这个检测器查找代码中忽略了不应该忽略的方法返回值的地方。这种情况的一个常见例子是在调用 String方法时:
忽略返回值的例子
String aString = "bob";
b.replace('b', 'p');
if(b.equals("pop"))
这个错误很常见。在第 2 行,程序员认为他已经用 p 替换了字符串中的所有 b。确实是这样,但是他忘记了字符串是不可变的。所有这类方法都返回一个新字符串,而从来不会改变消息的接收者。
Null 指针示例
Person person = aMap.get("bob");
if (person != null) {
person.updateAccessTime();
}
String name = person.getName();
在这个例子中,如果第 1 行的 Map不包括一个名为“bob”的人,那么在第 5 行询问 person的名字时就会出现 null 指针异常。因为 FindBugs 不知道 map 是否包含“bob”,所以它将第 5 行标记为可能 null 指针异常。
初始化之前读取字段
这个检测器寻找在构造函数中初始化之前被读取的字段。这个错误通常是——尽管不总是如此——由使用字段名而不是构造函数参数引起的。
在构造函数中读取未初始化的字段
public class Thing {
private List actions;
public Thing(String startingActions) {
StringTokenizer tokenizer = new StringTokenizer(startingActions);
while (tokenizer.hasMoreTokens()) {
actions.add(tokenizer.nextToken());
}
}
}
在这个例子中,第 6 行将产生一个 null 指针异常,因为变量 actions还没有初始化.
命名检查
对标准 Java 命令规范的测试:变量名称不应太短;方法名称不应过长;类名称应当以小写字母开头;方法和字段名应当以小写字母开头,等等。
未使用的代码检查
查找从未使用的私有字段和本地变量、执行不到的语句、从未调用的私有方法,等等。
嵌套检查
例如: switch 语句应当有 default 块,应当避免深度嵌套的 if 块,不应当给参数重新赋值,不应该对 double 值进行相等比较。
导入语句检查
检查 import 语句的问题,比如同一个类被导入两次或者被导入 java.lang 的类中。
JUnit 测试检查
查找测试用例和测试方法的特定问题,例如方法名称的正确拼写,以及 suite() 方法是不是 static 和 public。
字符串检查
找出处理字符串时遇到的常见问题,例如重复的字符串标量,调用 String 构造函数,对 String 变量调用 toString() 方法。
括号检查
检查 for、 if、 while 和 else 语句是否使用了括号。
代码尺寸检查
测试过长的方法、有太多方法的类以及重构方面的类似问题。
终结函数检查
因为在 Java 语言中, finalize() 方法不是那么普遍,它们的使用规则虽然很详细,但是人们对它们相对不是很熟悉。这类检查查找 finalize() 方法的各种问题,例如空的终结函数,调用其他方法的 finalize() 方法,对 finalize() 的显式调用,等等。
克隆检查
用于 clone() 方法的新规则。凡是重写 clone() 方法的类都必须实现 Cloneable, clone() 方法应该调用 super.clone(),而 clone() 方法应该声明抛出 CloneNotSupportedException 异常,即使实际上没有抛出异常,也要如此。
耦合检查
查找类之间过度耦合的迹象,比如导入内容太多;在超类型或接口就已经够用的时候使用子类的类型;类中的字段、变量和返回类型过多等。
异常检查
针对异常的检查:不应该声明该方法而抛出 java.lang.Exception 异常,不应当将异常用于流控制,不应该捕获 Throwable,等等。
日志检查
查找 java.util.logging.Logger 的不当使用,包括非终状态(nonfinal)、非静态的记录器,以及在一个类中有多个记录器。
Open—Close检查
检查文件或通讯方面,是否忘记Close的情况。
其它检查
FindBugs 网站提供了完整的 缺陷清单及说明。
构建自己的规则集
可以构建自己的规则集