FindBugs是一种java代码的静态分析工具,无需开发人员费劲就能找出代码中可能存在的缺陷。FindBugs 不注重样式或者格式,它试图只寻找缺陷或者潜在的性能问题。

第一步,http://sourceforge.net/projects/findbugs/files/findbugs%20eclipse%20plugin/下载zip包,解压到eclipse的plugins目录,重新启动eclipse。

第二步,工程右键中应该出现了FindBugs,点击应用。

Bug: Call to equals() comparing different types
Pattern id: EC_UNRELATED_TYPES, type: EC, category:
CORRECTNESS

解释:

两个不同类型的对象调用equals方法,如果equals方法没有被重写,那么调用object的==,永远不会相等。

解决方法

应该改为str.toString()

Bug: Check
for oddness that won't work for negative numbers
Pattern id: IM_BAD_CHECK_FOR_ODD, type: IM, category:
STYLE

解释:

如果row是负奇数,那么row % 2 == -1,

解决方法:

考虑使用x & 1 == 1或者x % 2 != 0

Bug:
PerfmSingleGraphPanel$RSCategory defines equals and uses Object.hashCode()
Pattern id: HE_EQUALS_USE_HASHCODE, type: HE, category:
BAD_PRACTICE

解释:

重载了equals方法,却没有重载hashCode方法,如果使用object自己的hashCode,我们可以从JDK源代码可以看到object的hashCode方法是native的,它的值由虚拟机分配(某种情况下代表了在虚拟机中的地址或者唯一标识),每个对象都不一样。

  equals用于判定两个对象是否为同一对象,程序员得根据自己的需要重写这个方法来达到对象比较的目的。
hashcode是用来提高效率的,HashSet和HashMap是基于hashcode方法来查找对象的,所以你在使用这些类的时候一定要覆盖hashcode方法。
而非散列的Set和Map,例如TreeSet,TreeMap等,它们只需equals方法就可以唯一确定对象的身份。

解决方法:

为了使你写的类能够高效地应用于HashMap/HashTable,请重写hashcode方法。

Bug: "." used for regular expression
Pattern id: RE_POSSIBLE_UNINTENDED_PATTERN, type: RE, category:
CORRECTNESS

解释:

String的split方法传递的参数是正则表达式,正则表达式本身用到的字符需要转义,如:句点符号“.”,美元符号“$”,乘方符号“^”,大括号“{}”,方括号“[]”,圆括号“()” ,竖线“|”,星号“*”,加号“+”,问号“?”等等,这些需要在前面加上“\\”转义符。

解决方法:

在前面加上“\\”转义符。

Bug:
WindowHandlerManager$MySingleSelectionModel is Serializable; consider declaring
a serialVersionUID
Pattern id: SE_NO_SERIALVERSIONID, type: SnVI, category:
BAD_PRACTICE

解释:

实现了Serializable接口,却没有实现定义serialVersionUID字段,序列化的时候,我们的对象都保存为硬盘上的一个文件,当通过网络传输或者其他类加载方式还原为一个对象时,serialVersionUID字段会保证这个对象的兼容性,考虑两种情况:

  1. 新软件读取老文件,如果新软件有新的数据定义,那么它们必然会丢失。
  2. 老软件读取新文件,只要数据是向下兼容的,就没有任何问题。

序列化会把所有与你要序列化对象相关的引用(包括父类,特别是内部类持有对外部类的引用,这里的例子就符合这种情况)都输出到一个文件中,这也是为什么能够使用序列化能进行深拷贝。这种序列化算法给我们的忠告是,不要把一些你无法确定其基本数据类型的对象引用作为你序列化的字段(比如JFrame),否则序列化后的文件超大,而且会出现意想不到的异常。

解决方法:

定义serialVersionUID字段

Bug:
ToStringComparator implements Comparator but not Serializable
Pattern id: SE_COMPARATOR_SHOULD_BE_SERIALIZABLE, type:
Se, category: BAD_PRACTICE

解释:

ToStringComparator类实现了Comparator接口却没有实现Serializable接口。

Comparator提供了比较的一句,利用Collections.sort可完成排序。

为了能够序列化Treemap和TreeSet,那么它们所添加的类,如果实现了Comparators必须支持Serializable接口。

解决方法:

实现Serializable接口并定义serialVersionUID字段

Bug:
ManageItem defines equals(ManageItem) method and
uses Object.equals(Object)
Pattern id: EQ_SELF_USE_OBJECT, type: Eq, category:
CORRECTNESS

解释:

这是重载,不是覆盖,除非你能保证其他人调用这个方法传入的参数都是ManageItem 的,否则会调用Object的boolean equals(Object)方法,这样的话根本就不会跑到这个方法里来。

解决方法:

如果你想覆盖父类的方法,请在上面加上@Override注解,它会防止这种错误的出现。

Bug: Dead
store to date
Pattern id: DLS_DEAD_LOCAL_STORE, type: DLS, category:
STYLE

解释:

定义了却未使用的变量。

解决方法:

大胆的去掉或者注释掉。

Bug:
Doomed test for equality to NaN
Pattern id: FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER, type: FE, category:
CORRECTNESS

解释:

Nan很特殊(表示未定义和不可表示的值),没有任何值跟它相等,包括它自身,所以x ==
Double.NaN永远返回false。

解决方法:

如果要检查x是特殊的,不是一个数值,请用Double.isNaN(x)方法。

Bug:
DBExportTask2.exportDBRecords(DBExportProperty, String) forces garbage
collection; extremely dubious except in benchmarking code
Pattern id: DM_GC, type: Dm, category:
PERFORMANCE

解释:

有两点:

  1. System.gc()只是建议,不是命令,JVM不能保证立刻执行垃圾回收。
  2. System.gc()被显示调用时,很大可能会触发Full GC

GC有两种类型:Scavenge GCFull GCScavenge GC一般是针对年轻代区(Eden区)进行GC,不会影响老年代和永生代(PerGen),由于大部分对象都是从Eden区开始的,所以Scavenge GC会频繁进行,GC算法速度也更快,效率更高。

但是Full GC不同,Full GC是对整个堆进行整理,包括Young、Tenured和Perm,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。

解决方法:

去掉System.gc()

Bug:
IPv4Document.m_strInitString isn't final but should be
Pattern id: MS_SHOULD_BE_FINAL, type: MS, category:
MALICIOUS_CODE

解释:

使用public和protected,别的包可以轻易修改它,如果你不想它被修改,请使用final。

封装很重要,不管是从维护方面和技术方面来说,都很重要,就算要给别人共享,也要提供get方法,特别是在并发环境中,get方法也应该是同步的。

解决方法:

加上final或者变为private的。

Bug:
ActionPatternManager.m_This should be package protected
Pattern id: MS_PKGPROTECT, type: MS, category:
MALICIOUS_CODE

解释:

Findbugs说,静态字段m_oThis应该是包权限的。

单例模式??这是神马单例模式?字段不是private,还是单例模式吗?

解决方法:

修改protected为private,然后将单例模式实现方式改为恶汉,或者双重校验锁定。

Bug:
Incorrect lazy initialization and update of static field
MonitorRuleManager.m_This
Pattern id: LI_LAZY_INIT_UPDATE_STATIC, type: LI, category:
MT_CORRECTNESS

解释:

这是一个多线程的BUG,多线程的问题之所以很严重,是因为我们很难复现解决它,但它又是的确存在的,它总是在关键时候爆发,让你感到很郁闷。

解决方法:

加上synchronized,改成饿汉模式,或者使用双重校验锁。

public class Singleton {

    private volatile static Singleton singleton;

      private Singleton (){}

      public static Singleton getSingleton() {

      if (singleton == null) {

        synchronized (Singleton.class) {

              if (singleton == null) {

singleton = new Singleton();

}

}

}

return singleton;

}

}

Bug:
Method JTAMainFrame.initView(JFrame) makes inefficient use of keySet iterator
instead of entrySet iterator
Pattern id: WMI_WRONG_MAP_ITERATOR, type: WMI, category:
PERFORMANCE

解释:

很多人都这样遍历Map,没错,但是效率很低,先一个一个的把key遍历,然后在根据key去查找value,这不是多此一举么,为什么不遍历entry(桶)然后直接从entry得到value呢?它们的执行效率大概为1.5:1(有人实际测试过)。

解决方法:

  for (Map.Entry<String, JMenu> entry : menuList.entrySet()) {

       mb.add(entry.getValue());

}

Bug:
SingleNePollConfigDialog.collectValues(Hashtable) may expose internal
representation by storing an externally mutable object into
SingleNePollConfigDialog.values
Pattern id: EI_EXPOSE_REP2, type: EI2, category:
MALICIOUS_CODE

解释:

参数values保存在当前线程的执行栈中,而this.values保存在堆上,它们同时指向同一个对象,对参数values的任何操作都会影响到this.values,如果你知道这一点,而且本意就是这样的,那么你可以忽略上面这些话,但是下面这些话你应该好好听听。

这是一段正确的代码,但不是一段可维护性强、可理解性强的代码,参数代表操作的条件,它们应该是只读的,我们不应该对它直接进行操作或者赋值。

解决方法:

如果把上面对参数values的操作都改成this.values。

Bug:
temsLoader.getItemsWithPriority() may expose internal representation by
returning ItemsLoader.m_htItemsWithPriority
Pattern id: EI_EXPOSE_REP, type: EI, category:
MALICIOUS_CODE

解释:

刚开始一看挺纳闷的,这个方法有什么问题吗?某些数据集合不应该直接对外提供public返回方法,提供了get方法,但实际上可以任意修改里面的数据。

解决方法:

如果你确定这些数据集合不应该被外界修改,那么对于基本数据类型,你提供get方法即可,对于引用,get方法里的返回值应该是数据的拷贝。

Bug:
Method call passes null for nonnull parameter of queryScriptData(ObjService)
Pattern id: NP_NULL_PARAM_DEREF, type: NP, category:
CORRECTNESS

解释:

当getAllListFiles方法发生了任何异常(checked和unchecked),allFiles都为null,关键是在queryScriptData方法里,并没有对参数是否为null进行判断,它直接调用了参数对象上面的方法,这肯定会发生空指针异常。

一个优秀的程序员,在过马路时都要向两边看一下,在写一个方法时,首先要考虑的就是对方法参数的有效性判断。

解决方法:

在queryScriptData方法里对参数进行有效性判断。

Bug:
TopoCardManagerAction.processLocalCard(Hashtable) invokes inefficient Boolean
constructor; use Boolean.valueOf(...) instead
Pattern id: DM_BOOLEAN_CTOR, type: Dm, category:
PERFORMANCE

解释:

不必创建一个新的Boolean对象,使用Boolean.valueOf方法可以重用Boolean.FALSE和Boolean.TRUE对象。

我们可以从API中可以看到public Boolean(boolean value)方法的解释:注:一般情况下都不宜使用该构造方法。若不需要新 的实例,则静态工厂 valueOf(boolean) 通常是一个更好的选择。这有可能显著提高空间和时间性能。

解决方法:

使用Boolean.valueOf方法或者直接返回Boolean.FALSE和Boolean.TRUE对象。

FindBugs简单应用的更多相关文章

  1. Java静态代码分析工具——FindBugs插件的安装与使用

    1 什么是FindBugs FindBugs 是一个静态分析工具,它检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题.有了静态分析工具,就可以在不实际运行程序的情况对软件进行分 ...

  2. FindBugs插件的安装与使用

    转载:http://www.cnblogs.com/kayfans/archive/2012/06/18/2554022.html 1 什么是FindBugs FindBugs 是一个静态分析工具,它 ...

  3. 源代码扫描工具Fortify SCA与FindBugs的简单对比

    前段时间因为工作原因需要对java源代码进行扫描,现结合使用经验对静态代码扫描工具Fortify SCA与FindBugs进行一个简单的对比. 一.Fortify SCA Fortify SCA是由全 ...

  4. MyEclipse2014 设备 checkstyle、PMD、findbugs 最简单的方法 详细说明

    最近的实验需要的代码审查和应用程序性能优化.在需求MyEclipse安装某些插件,由于如今的MyEclipse版本号和大多数教程的不一样了,一些安装选项也已经改变,所以安装起来非常费事,通过不断的尝试 ...

  5. AndroidStudio 插件 之 Findbugs 安装与简单使用教程

    http://blog.csdn.net/u013132758/article/details/70187846 http://blog.csdn.net/jdsjlzx/article/detail ...

  6. FindBugs 入门——帮你减少代码中的bug数

    FindBugs 入门 FindBugs 作用 开发人员在开发了一部分代码后,可以使用FindBugs进行代码缺陷的检查.提高代码的质量,同时也可以减少测试人员给你报的bug数. 代码缺陷分类 根据缺 ...

  7. Eclipse的FindBugs插件

      Eclipse的FindBugs插件     问题提出: 当我们编写完代码,做完单元测试等各种测试后就提交正式运行,只能由运行的系统来检测我们代码是否有问题了,代码中隐藏的错误在系统运行的过程中被 ...

  8. 提高代码质量 CheckStyle FindBugs PMD

    提高代码质量-工具篇 注:这是一篇翻译文章,原文:How to improve quality and syntax of your Android code,为了理解连贯,翻译过程中我修改了一些陈述 ...

  9. Findbugs介绍及使用方法

    1.   简介 Findbugs 是一个静态分析工具,它检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题.利用这个工具,就可以在不实际运行程序的情况对软件进行分析.它可以帮助改 ...

随机推荐

  1. 平安E行销扫脸打卡/人寿国寿e店云参会钉钉考勤,原来这么轻易被破解!

    由于近几年人们的保险意识越来越强,身边有很多朋友都在中国人寿,中国平安等保险公司上班薪水高,工作自由,又可以学习很多保险理财的知识,每天早会个2~3个小时,剩下的基本都是自己的时间,(vx:99508 ...

  2. Hive_UDF函数中集合对象初始化的注意事项

    UDF函数中定义的集合对象何时初始化 udf函数放在sql中对某个字段进行处理,那么在底层会创建一个该类的对象,这个对象不断的去调用这个evaluate(...)方法,截图如下:   1.1 如果说对 ...

  3. java finally深入探究

    When---什么时候需要finally: 在jdk1.7之前,所有涉及到I/O的相关操作,我们都会用到finally,以保证流在最后的正常关闭.jdk1.7之后,虽然所有实现Closable接口的流 ...

  4. linux服务器,svn认证失败,配置问题,防火墙等等

    之前自己还真没设置过SVN,今天亲自动手,错误百出,真是够头疼的.在网上随便找了一篇文章,就按照文章介绍开始安装.怎么安装和设置我就不说了,这里主要记录遇到的问题. 1.不知道该怎么设置 svn:// ...

  5. 浅谈linux虚拟内存结构

    一个虚拟存储器系统要求硬件和软件之间紧密写作(mmu(内存管理单元,虚拟地址到物理地址的翻译),TLB块表(虚拟地址到物理地址index,虚拟寻址),l1,l2,l3高速缓存(物理单元数据)物理寻址) ...

  6. Jade报错:Invalid indentation,you can use tabs or spaces but not both问题

    现象:通过html生成jade文件之后,更改jade文件时,语句没什么问题的情况下,jade文件编译不通过,报错:Invalid indentation,you can use tabs or spa ...

  7. Spring Boot实战:拦截器与过滤器

    一.拦截器与过滤器 在讲Spring boot之前,我们先了解一下过滤器和拦截器.这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的.在分析两者的区别之前,我们先理解一下AOP的概念,A ...

  8. Linux安装mysql 在/etc下没有my.cnf 解决办法

    进入 /usr/share/mysql  将my-medium.cnf 移动到etc 并且改名为my.cnf

  9. 要学的东西太多了,还想学习opencv

    资料先放这里,以后好好学 http://m.blog.csdn.net/column/details?alias=opencv-tutorial eclipse加载opencv库成功! B站视频教程资 ...

  10. pycharm python模版样式

    问题: 我想在创建新的一些python程序的时候,希望在新文件开头添加python版本声明和一些关于时间相关的模版数据 那,如何解决? 1. pycharm ---> setting ---&g ...