前言
Findbugs是使用静态分析来检测java代码中的潜在错误,保证代码符合一定规则的辅助工具。
本文针对AndroidStudio如何使用findbugs插件的使用和findbugs过滤进行总结,主要包含:
- 如何安装和使用findbugs插件
- 如何屏蔽掉不能修改的findbugs
- 如何快速高效对findbugs进行修改
使用findbugs工具,无非是检测和修改旧bugs以及对新增代码bugs进行监测,为了防止旧bugs和新增bugs掺杂在一起,影响检测效率,如何屏蔽掉不能修改的findbugs是很重要的,因此标为红色。
1. 安装和使用findbugs插件
1.1安装步骤
Step1:File->Settings->Plugins搜索Findbugs插件
如下图:
Step2:点击安装,重启AndroidStudio 生效
Step3:查看安装成功
1.2使用说明
如下图标识,findbugs工具分为6个区。
SEC 1:代码检测功能区,支持检测currentFile、package、module、project。
SEC 2:bug显示控制区,可以分类显示,分package显示
SEC 3:bug代码检索区,支持选中bug跳转,支持bug临时显示
SEC 4:导出/入错误集合,支持输出bug report
SEC 5:bug分类显示区,可以按照显示控制设置,显示bug
SEC 6:bug详情显示区,可以显示bug描述和修改建议
2. 屏蔽掉那些不想显示的bugs
使用findbugs的痛点之一,就是检测出很多无效bug,混淆视听,比如google提供的jar包,比如资源文件自动生成的R.java内容,还有就是不能改的bug。
屏蔽掉这些bug,不仅能够帮助findbugs更清晰有效,还能保证只要新增代码,就能够快速检测新增bug。屏蔽bug规则,可参考:
http://findbugs.sourceforge.net/manual/filter.html
这里根据我的代码实践,介绍怎么屏蔽findbugs。
Step1:写filter.xml
典型的几类屏蔽如下:
不同的标签,表示不同的过滤选项。可参考上述网址,配合下边代码查看,实践一下就清楚了。
<?xml version="1.0" encoding="utf-8"?>
<FindBugsFilter>
<Match>
<!--过滤掉Google jar包-->
<Or>
<Package name="~android\.support\.design.*" />
<Package name="~android\.support\.v7.*" />
<Package name="~android\.support\.v4.*" />
</Or>
</Match>
<Match>
<!--过滤生成文件-->
<Or>
<Class name="~.*\.*id*"/>
<Class name="~.*\.*styleable*"/>
<Class name="~.*\.*attr*"/>
</Or>
</Match>
<Match>
<!--过滤几个类型的bug-->
<Or>
<Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE"/>
<Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/>
</Or>
</Match>
<Match>
<!--过滤某个变量的某个bug类型-->
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD" />
<Or>
<Class name="~com\.ainirobot\.maptool\.map\.Parameter"/>
<Filed name="*.sharedPreferences"/>
</Or>
</Match>
<Match>
<!--过滤某个方法的某个bug类型-->
<Bug pattern="IS2_INCONSISTENT_SYNC"/>
<Or>
<Class name="~com\.ainirobot\.maptool\.util\.Singleton"/>
<Method name="get"/>
</Or>
</Match>
</FindBugsFilter>
<可以看到过滤类型基本包含:
- Jar包
- Class
- 成员变量
- 方法
- bug类型Google jar包-->
Step2:添加到exlude配置中
如图,1,2,3,4,5步,就完成了filter的添加,当你再次运行findbugs,这些过滤掉的bugs你就看不到了,此处应该有掌声。
体验过编写filter.xml后,你就要根据自己的需求来过滤了,祝好运。
3. 几种bug类型和修改
1. SS_SHOULD_BE_STATIC (Unread field: should this field be static?)
用final定义的filed,一般都需要声明为static
2. URF_UNREAD_FIELD (Unread field)
定义了,但没有使用的filed,考虑删除
3. UUF_UNUSED_FIELD (Unused field)
同2,定义了但是没有使用的filed,考虑删除
4. SIC_INNER_SHOULD_BE_STATIC (Should be a static inner class)
有些内部类,并没有使用其所在定义类的引用,因此可以声明为static。
5. DM_BOXED_PRIMITIVE_FOR_PARSING (Boxing/unboxing to parse a primitive)
将String类型转化为基本数据类型,使用parseXXX比xxx.valueOf更高效。
6. SBSC_USE_STRINGBUFFER_CONCATENATION (Method concatenates strings using + in a loop)
使用“+”作为String的连接符很低效,因为其底层实现是转化为StringBuffer/StringBuilder来实现的,因此直接使用StringBuffer/StringBuilder的append方法连接Strings。
7. SF_SWITCH_NO_DEFAULT (Switch statement found where default case is missing)
Switch case确实default分支
8. ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD (Write to static field from instance method)
尽量不要在实例的非静态方法里,去写静态filed,由于静态field是class共享,可能会出现问题。
9. DLS_DEAD_LOCAL_STORE (Dead store to local variable)
没有使用的局部变量删除。
10. NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE (Possible null pointer dereference due to return value of called method) NP_NULL_ON_SOME_PATH (Possible null pointer dereference)
某些分支有空指针的可能,需要注意判空
11. DB_DUPLICATE_BRANCHES (Method uses the same code for two branches)
不同分支,同样的处理代码。
12. JLM_JSR166_UTILCONCURRENT_MONITORENTER (Synchronization performed on util.concurrent instance)
使用java.util.concurrent package (or its subclasses)做锁对象,改为使用普通对象作为锁即可。
13. HE_EQUALS_USE_HASHCODE (Class defines equals() and uses Object.hashCode())
复写equals后,必须复写hashCode,否则会在使用hashMap等数据结构时出错。
14. ES_COMPARING_PARAMETER_STRING_WITH_EQ (Comparison of String parameter using == or !=)
判断String相等,尽量使用Objects.equals的工具类方法,而不要使用==。
15. OS_OPEN_STREAM (Method may fail to close stream)OS_OPEN_STREAM (Method may fail to close stream)
文件流注意关闭,一定要用try finally关闭,否则就会报这个错误。
16. MS_SHOULD_BE_FINAL (Field isn't final but should be)
一个集合定义为static,可能需要定义为final,同时如果不想被外部引用更改,需要使用Collections.unmodifiableMap来进行赋值。