FindBugs错误整理

前言

关于FindBugs的安装使用可以参考AndroidStudio 插件 之 Findbugs 安装与简单使用教程
最近使用FindBugs找到一篇很棒的博文http://www.cnblogs.com/java-zone/articles/3118592.html 总结了很多常见的bug解析.然而,作者Anthony无顺序的排版,导致查找相当困难,这里结合官方文档,按字母顺序排列,以便准确定位查找.

定位错误

不知道错误在那看的 看下图Android Studio:
这里写图片描述

错误列表

B

BC_VACUOUS_INSTANCEOF

解释:
因为getSelectedTreeNode方法返回类型就是TopoTreeNode,所以if里的instanceof测试永远为true,除非它是null,确保你没有其他的逻辑上的误解,你这样写,会让其他人丈二和尚摸不着头脑。
解决方法:
去掉instanceof检测。

C

CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE

解释:
SoundProperty类实现了clone方法,但是没有实现Cloneable接口,当然这没有任何问题,但是你应该知道你为什么这么做。
解决方法:
最好实现Cloneable接口

D

DM_BOOLEAN_CTOR

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

DLS_DEAD_LOCAL_STORE

解释:
对本地变量定义了之后未使用到,编译器能够做优化处理,也就是在编译之后的class文件中删除这些本地变量。:
解决方法:
大胆的去掉或者注释掉。
误报的案例:
IntegralItemDO integralItem = new IntegralItemDO();
是一个局部的变量,不需要定义到外部去,定义在外部,可能会变成一个无效的变量。

DM_GC

解释:
1. System.gc()只是建议,不是命令,JVM不能保证立刻执行垃圾回收。
2. System.gc()被显示调用时,很大可能会触发Full GC。
GC有两种类型:Scavenge GC和Full GC,Scavenge GC一般是针对年轻代区(Eden区)进行GC,不会影响老年代和永生代(PerGen),由于大部分对象都是从Eden区开始的,所以Scavenge GC会频繁进行,GC算法速度也更快,效率更高。但是Full GC不同,Full GC是对整个堆进行整理,包括Young、Tenured和Perm,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。
解决方法:
去掉System.gc()

DM_FP_NUMBER_CTOR

解释:
采用new Ddouble(double)会产生一个新的对象,采用Ddouble.valueOf(double)在编译的时候可能通过缓存经常请求的值来显著提高空间和时间性能。
解决方法:
采用Ddouble.valueOf方法

DM_NUMBER_CTOR

说明:
[参考]http://www.cnblogs.com/hyddd/articles/1391318.html
FindBugs推荐使用Integer.ValueOf(int)代替new Integer(int),因为这样可以提高性能。如果当你的int值介于-128~127时,Integer.ValueOf(int)的效率比Integer(int)快大约3.5倍。
下面看看JDK的源码,看看到Integer.ValueOf(int)里面做了什么优化:
public static Integer valueOf(int i) { final int offset = 128; if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); } private static class IntegerCache { private IntegerCache(){} static final Integer cache[] = new Integer[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache = new Integer(i - 128); } }
从源代码可以知道,ValueOf对-128~127这256个值做了缓存(IntegerCache),如果int值的范围是:-128~127,在ValueOf(int)时,他会直接返回IntegerCache的缓存给你。
所以你会看到这样的一个现象:
public static void main(String []args) { Integer a = 100; Integer b = 100; System.out.println(a==b); Integer c = new Integer(100); Integer d = new Integer(100); System.out.println(c==d); }
结果是:
true false
因为:java在编译的时候 Integer a = 100; 被翻译成-> Integer a = Integer.valueOf(100);,所以a和b得到都是一个Cache对象,并且是同一个!而c和d是新创建的两个不同的对象,所以c自然不等于d。
再看看这段代码:
public static void main(String args[]) throws Exception{ Integer a = 100; Integer b = a; a = a + 1; //或者a++; System.out.println(a==b); }
结果是:false
因为在对a操作时(a=a+1或者a++),a重新创建了一个对象,而b对应的还是缓存里的100,所以输出的结果为false。

DP_DO_INSIDE_DO_PRIVILEGED

解释:
使用public和protected,别的包可以轻易修改它,如果你不想它被修改,请使用final。
封装很重要,不管是从维护方面和技术方面来说,都很重要,我不明白为神马有那么多的人把变量都写成public的(就算要给别人共享,也要提供get方法),特别是在并发环境中,特别特别注意类变量的共享,而且特别特别特别注意共享的这个变量是否是线程安全的。
解决方法:
加上final

E

EC_UNRELATED_TYPES

解释:
两个不同类型的对象调用equals方法,如果equals方法没有被重写,那么调用object的==,永远不会相等;如果equals方法被重写,而且含有instanceof逻辑,那么还是不会相等。
解决方法:
应该改为str.toString()

EI_EXPOSE_REP

解释:
刚开始一看挺纳闷的,这个方法有什么问题吗?后来仔细看一下,发现返回值都有一个特点,它们都是集合数组之类的,我想findBugs的本意是,某些数据集合不应该直接对外提供public返回方法,即使表面上提供了get方法,但实际上可以任意修改里面的数据。
解决方法:
如果你确定这些数据集合不应该被外界修改,那么对于基本数据类型,你提供get方法即可,对于引用,get方法里的返回值应该是数据的拷贝。

EI_EXPOSE_REP2

解释:
参数values保存在当前线程的执行栈中,而this.values保存在堆上,它们同时指向同一个对象,对参数values的任何操作都会影响到this.values,如果你知道这一点,而且本意就是这样的,那么你可以忽略上面这些话,但是下面这些话你应该好好听听。
这是一段正确的代码,但不是一段可维护性强、可理解性强的代码,参数代表操作的条件,它们应该是只读的&#x

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值