Bug: Computation of average could overflow
Pattern id: IM_AVERAGE_COMPUTATION_COULD_OVERFLOW, type: IM, category: STYLE 解释:
参照了Findbugs的解释,(low+high)/2当平均数过大的时候(难道是超过了int最大值?) 会溢出,会出现一个负值,此问题出现在早期实现的二进制搜索和归并排序,但是已经被修
复了。参见Joshua Bloch(google首席java架构师)widely publicized the bug pattern(需翻 墙).
解决方法:
建议使用无符号右移位运算符:use (low+high) >>> 1
22. SC_START_IN_CTOR
Bug: new AsyncCentral() invokes AsyncCentral$FireThread.start() Pattern id: SC_START_IN_CTOR, type: SC, category: MT_CORRECTNESS 解释:
构造方法里重启新的线程,我还是第一次见过这样写的。 首先说明三点:
1. 对象的创建一般分两步走,在堆上new对象操作,执行
什么我们开发人员看见的只有一步,那是因为JVM不想让开发人员在这个过程中插上一 脚,破坏对象的初始化流程。
2. 类的加载和初始化是由虚拟机保证同步的,但是对象的生成和初始化就没有任何同步机
制来保证了。
3. 构造器不能加synchronized,是一项程序语言设计上的选择(见:JLS 8.8.3 Constructor
Modifiers),正常情况下,是不需要加上synchronized,但不代表所有的情况都不要加上 synchronized,更不能认为一个构造器隐含的就是一个synchronized。
那什么时候构造方法需要同步呢?通常来说,
据),所以我们经常不用关心构造方法同步的问题。但是上述情况就不一样了,在构造方法 中新启线程,如果AsyncCentral是一个状态类,FireThread线程极有可能对AsyncCentral的 状态进行反复读取和写入,更严重的一种情况是,AsyncCentral有父类,极有可能在父类的 构造方法还没开始前,FireThread线程就已经开始执行并对AsyncCentral的状态进行“破坏” 了。这个时候,就有两个线程来对AsyncCentral的状态进行操作了(一个是执行
多数时候,我们没有发现,可能是AsyncCentral类没有状态,或者是时候未到,我想说的是, 我们写的大部分程序都存在同步的问题,本例子就是其中一个,值得我们好好思考。
另一种理解(觉得更靠谱,来自于Java.Concurrency.in.Practice)叫做“对象逃逸”,意思就 是说在构造方法里,this是可以访问的到的,同一时间,FireThread线程而是可以访问到this 对象的,所以这时候this就从
不要再构造方法中新启线程,可以提供init方法,其他方法根据实际情况而定。
23. EQ_SELF_USE_OBJECT
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注解,它会防止这种错误的出现(透露 一个小细节,JDK1.5覆盖接口方法时加上@Override编译器会报错,JDK1.6修正,这可能是 当初实现者对@Override注解理解的问题)。
24.DLS_DEAD_LOCAL_STORE
案例二:
Bug: Dead store to date
Pattern id: DLS_DEAD_LOCAL_STORE, type: DLS, category: STYLE 解释:
先看看,我们的程序有多少个这样的例子:
真是伤不起啊,不知道当时的作者这是神马意图?手滑?还是眼花?虽然说这不是神马问题, 也不会对程序性能造成多大的影响,但是这就像一颗沙子,我们每个程序员对待程序都应该 是眼里不能进沙子的态度,当然,你非要这么写,我也没神马可说的。 By the way:
对本地变量定义了之后未使用到,编译器能够做优化处理,也就是在编译之后的class文件 中删除这些本地变量。方法是在eclipse的Preferences里将以下的钩去除:
解决方法:
大胆的去掉或者注释掉。 误报的案例:
上述案例二种:
IntegralItemDO integralItem = new IntegralItemDO();
是一个局部的变量,不需要定义到外部去,定义在外部,可能会变成一个无效的变量。
25.FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER