听说Integer有bug?1000不等于1000?

bug?

前几天有位朋友找我,说:“老哥,老哥,我好像发现了Integer一个bug,你帮我看看什么情况?”,说完给了我两个很简单的demo,上代码。

在这里插入图片描述
100 == 100

1000 == 1000

通过代码,我们可以看到,这是很简单的“100100”、“10001000”,但是为什么一个是“true”,一个是“false”,难道真的是bug?

使用Integer的场景

我们平时用Integer,都是用来操作整型数值相关操作,比如Model里面的自增主键id,类型标识type等等。

比如我们有个类型,性别,1 男 2 女;那么我们展示到页面的代码一般会这么写:

public static final Integer MAN = 1;

public static final Integer WOMAN = 1;

... ...

if(MAN == user.getSex()) {

return "男";

} else if(WOMAN == user.getSex()) {

return "女";

}

很常见,基本也没遇到过问题,因为我们也很少类型超过几百上千的,只有特殊场景的设计才有。

Integer是什么,怎么正确比较

我们先看看Integer的定义,打开Integer的源代码文件:
在这里插入图片描述
class Ineger

通过截图中的代码,我们可以看到,Integer是class,所以Integer是对象。

我们都知道对象的“==”比较,是比较的两引用对象的指针(内存地址)是否相等,也就是是否指向同一对象。既然是对象,那么Integer的正确比较姿势,肯定是“equals”了,即“a.equals(b)”。

我们再回头看前面的例子,“a”和“b”并不是同一个对象。那为什么“100”可以,“1000”就不可以?

自动装箱拆箱

装箱,是自动将基本数据类型转换为包装器类型;

拆箱,是自动将包装器类型转换为基本数据类型;

在这里插入图片描述

在这里我们不对“装箱拆箱”做太多的解释,后续我们再开专题讨论。

回到Integer,简单了解下其装箱拆箱分别做了什么操作。

Integer类型的赋值给int类型,调用intValue()方法进行拆箱赋值;

int类型赋值给Integer,会调用valueOf()方法对int进行装箱赋值。

看下相应的源码:
在这里插入图片描述
intValue()
在这里插入图片描述
valueOf()
我们可以看到,除了“return new Integer(i)”,还有一段if判断,大致意思我们可以看出来,当在“IntegerCache.low”与“IntegerCache.high”区间的时候,会返回“IntegerCache.cache[]”的一个值。

好了,到此,我们可以看到,当装箱 Integer 的值在一定区间的时候,并不是“new”出来的,而是从 IntegerCache.cache[] 中取出来的。所以我们再看看 IntegerCache 是如何定义的。

Integer 缓冲池 IntegerCache

话不多说,先上源码:
在这里插入图片描述
IntegerCache

由于时间有限,我们就看看重点,

for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);

这两行代码,就是初始化了cache[]数组的值,每个值都是对应的数值的Integer对象。

1000 不等于 1000 还是bug吗?

到此,我们已经得知,几个重点:

  1. Integer 是对象
  2. Integer 值比较应该使用 equals()
  3. Integer 有个缓存池 IntegerCache,预初始化 -127 至 127 的 Integer 对象\

再看看demo,使用的是“==”并不是“equals()”,所以这并不是bug,而是比较的方式不对,正确的比较姿势是“equals()”,我们来实践一下看看。
在这里插入图片描述
在这里插入图片描述

举一反三

同样是装箱拆箱,Long是否也有缓存池呢?Double呢?

My Blog

blog.guijianpan.com

技术交流

在这里插入图片描述

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页