现象:
code review中发现有代码中用下面的方式比较Integer变量:
if (object.getA() == xxx) {
...
}
这种方式是有风险的,当整型数据的值超出-128-127的范围时,两个值相同的Integer变量用==比较会返回false。
来看看测试结果:
原因分析:
在Integer类中有一个IntegerCache类,来看看这个类的说明:
IntegerCache中定义了一个Integer数组,初始化-128到127之间的整型对象,也就是说,用Integer i1 = 127, i2 = 127;的方式定义两个对象i1和i2,实际上都会从这个cache中取到
同一个对象,"i1 == i2"比较i1和i2的内存地址,实际上是同一个对象,所以地址也相同,"i1 == i2"返回true,而i3和i4由于超出了127,所以重新生成两个对象,内存地址不一样,
"i3 == i4"返回false。
从上面jdk的注释中我们还看到,这个cache的上限是可以由参数-XX:AutoBoxCacheMax来设置的,我们来试试。
上面的代码再增加两个变量,以作对比,先运行一次:
可以看到,后面两个比较都返回false,因为都超出了127.
现在我们来把cache的上限设置为200试试:
运行结果:
此时,i3 == i4返回了true。
实际上,Double, Boolean这些类同样都有一个缓存,有兴趣的可以进入这些类的源码看看。
解决方案:
用Integer对象的equals方法来比较,或者用i1.intValue() == i2.intValue()来比较即可,此时请注意对null的判断。