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

技术交流

听说Integer有bug?1000不等于1000?的更多相关文章

  1. 糟糕,你写的 BUG 要被存1000年了!

    摘要:代码冰封,祖传千年! 把大象放在冰箱需要几步? 三步!把代码放在北极需要几步?纳尼? GitHub刚刚公布了一组照片,你写的代码(BUG)上周已经被打包运往北极保存. 只要你2月2日以前贡献过的 ...

  2. hide(1000)跟show(1000)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. NGUI panel 之下widget最大depth是1000,超过1000时OnClick会出问题!

    经过我的测试发现ngui widget的depth是有限制的!原本以为只要不同panel间的depth设置好了后无论widget depth如何设置都没问题,直到我们项目中出现奇怪的点击问题后才发现这 ...

  4. Java Integer于Int 进行==双等于的内存比较时的一些问题说明

    转自: https://blog.csdn.net/xingkongdeasi/article/details/79618421 部分有所修改: 前言: 越是简单的东西,我们往往越是没有去把它明白,但 ...

  5. java 中 sleep(1000) 和 wait(1000) 的区别?

    1.首先 sleep 方法是Thread类中的静态方法,他的作用是使当前线程暂时睡眠指定的时间,可以不用放在synchronized方法或者代码块中,但是 wait 方法是Object类的方法,它是使 ...

  6. 验证HashSet和HashMap不是线程安全

    JAVA集合类: java.util包下的HashSet和HashMap类不是线程安全的, java.util.concurrent包下的ConcurrentHashMap类是线程安全的. 写2个测试 ...

  7. Java基础教程——包装类

    Java出道之时,自诩为"纯面向对象的语言",意思是之前的所谓"面向对象语言"不纯. 但是,有人指责Java也不纯--8种基本类型并非类类型.为此,Java为他 ...

  8. C++ 类类型转换函数explicit 关键字

    标准数据之间会进行  隐式类型安全转换. 转换规则: 隐式类型转换的问题: #include <iostream> #include <string> using namesp ...

  9. 计算机中K到底是1000还是1024?

    1000和1024的争论,其实是传输领域和存储领域概念不清引起的;在传输领域,1秒钟传输多少字位(即b,bit),肯定是用10进制表示,所以是1kb=1000b,即1秒钟传输1000个比特位;就好像: ...

随机推荐

  1. 数据结构-二叉树、B树、B+树、B*树(整理版)

    1. 二叉树 二叉树的特点: ① 所有非叶子节点至多拥有两个儿子(Left和Right): ② 所有节点存储一个关键字: ③ 非叶子节点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: ...

  2. myisamchk 是用来做什么的?

    它用来压缩 MyISAM 表,这减少了磁盘或内存使用. MyISAM Static 和 MyISAM Dynamic 有什么区别? 在 MyISAM Static 上的所有字段有固定宽度.动态 MyI ...

  3. SpringBoot与SpringCloud的关系与区别?

    一.SpringBoot和SpringCloud简介 1.SpringBoot:是一个快速开发框架,通过用MAVEN依赖的继承方式,帮助我们快速整合第三方常用框架,完全采用注解化(使用注解方式启动Sp ...

  4. jQuery--文档处理案例

    需求 如上图,实现左右两边的选择菜单可以左右移动,'>'按钮一次只能移动被选中的一个菜单,'>>'按钮一次移动所有被选择的菜单,'>>>'按钮 将所有菜单进行移动, ...

  5. (转载)一篇文章带你分清楚JWT,JWS与JWE

    是JWS(JSON Web Signature),也往往导致了人们对于JWT的误解,但是JWT并不等于JWS,JWS只是JWT的一种实现,除了JWS外,JWE(JSON Web Encryption) ...

  6. elasticsearch 是如何实现 master 选举的 ?

    面试官:想了解 ES 集群的底层原理,不再只关注业务层面了. 前置前提: 1.只有候选主节点(master:true)的节点才能成为主节点. 2.最小主节点数(min_master_nodes)的目的 ...

  7. 关于 OOP 和设计模式?

    这部分包含 Java 面试过程中关于 SOLID 的设计原则,OOP 基础,如类,对象, 接口,继承,多态,封装,抽象以及更高级的一些概念,如组合.聚合及关联. 也包含了 GOF 设计模式的问题.

  8. 学习zabbix(八)

    一,Zabbix架构 zabbix 是一个基于 WEB 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.zabbix 能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制 ...

  9. H5进阶篇--实现微信摇一摇功能

    在HTML5中,DeviceOrientation特性所提供的DeviceMotion事件封装了设备的运动传感器时间,通过改时间可以获取设备的运动状态.加速度等数据(另还有deviceOrientat ...

  10. C# 委托专题

    单播委托:一个委托只指向一个方法: 多播委托:一个委托指向多个方法,形成一个方法链: Main是静态方法,里面只能引用静态方法,而不能引用实例方法: Main可以进行类的实例化,然后引用实例化后的方法 ...