findbugs使用有感(旧)

| Comments

最近抽出点时间来处理项目上庞大的findbugs问题,处理过程中总结了下面几类参见的毛病:

关于IO流

见过的有写response的outputStream,文件下载,数据导出。这些场景涉及流读取、写入和最后的关闭,是findbugs检查的重灾区. 解决办法是使用common-io库,常用的方法有IOUtils#copy,IOUtils#write,IOUtils#closeQuietly。

关于无效变量操作

包括变量使用后置null,没有被使用的变量,虽然这种findbugs问题很低级,不过在系统中仍然存在很多。 处理办法是

  1. 变量使用后置null是没什么用的,JVM的GC比想象中智能多了;
  2. 假如变量在稍后的处理过程一定会被赋值,则init是没有意义的。
    遵循的原则是相关的变量和操作集中在一起,缩短变量的作用域(同时,这样也对JVM比较友好)

关于对象的延时加载

系统中有些类实现了延时加载的singleton模式,还有的Action类中的实例变量使用了延时加载的方式。 很不幸的是,singleton的延时加载实现几乎都是错的, Action类的实例变量延时加载也没什么意义。 要实现singleton,最简单的方式是预加载方式,如果想做延时加载,可以使用内部静态类的实现方式。

关于执行效率

包括string的修改操作,map的遍历操作。如果有string的大量修改操作,应该使用StringBuffer或者StringBuilder (在jdk5以上,StringBuilder适用于大多数场合)。而对于map的遍历,应该使用entrySet而不是keySet,这些注意一下就ok了。 另外系统有很多DateFormater的东西,用了很多静态变量来提高效率,可惜jdk的日期库是非常烂的,DateFormater也不是线程安全的东西,应该避免使用静态变量。

关于异常处理

Exception is caught when Exception is not thrown 这个findbugs问题在系统出现非常多,也是最难处理的问题。从这个点 就可以看出系统实现非常混乱,本来属于不同抽象层次的代码都堆在一起了,没有层次之分。这个问题一般是需要修改到那段逻辑的时候才会去 解决,通过抽取方法/类的方式,把异常进行抽象化,最后借助框架层次上的异常统一处理逻辑就通常可以把Action上面的所有的try-catch干掉。

关于注释

这其实不是findbugs问题。可以发现java代码里边很多注释是没什么用的,包括一些显而易见的注释,方法注释(通常只有方法描述是有点意义,其他都是抄模板的) 注释写不好,还不如不写,正确的做法是尽量写出自文档化的代码。

Comments