【Java踩坑系列】01:Integer

The Integer class wraps a value of the primitive type int in an object. An object of type Integer contains a single field whose type is int.

Integer 类的介绍很简单,使用也一样简单,一般使用也不会出现什么问题,当然文章标题既然是踩坑系列,就说说自己工作中遇到过的关于Integer的坑吧。


背景:上家公司是传统行业,所在的部门开发了一款法院庭审系统,新版本发布前都经过严格的测试(考虑到软件的应用现场是法院等一些国家单位基于数据保密性等的原因现场测试难度较大),由于从公司版本发布到真正软件在现场环境运行可能是N个月之后,出现问题也难于排查,只能在公司环境进行复现,然后修改BUG。

问题出现:软件部署到现场,经过演示,测试一切顺利,法院开始使用,但是使用一段时间之后出现无法开庭的情况。

问题定位:进过调试,复现,最终问题定位在Integer比较相等的一段代码上。类似于下面的这段代码:

if(userLogin.getId() == userSjy.getId()){ // 允许开庭 }

逻辑很简单,就是当前的用户id和书记员id相等的时候允许开庭,否则不允许开庭。而这里的User.id 的类型是Integer,或许你会说很明显应该用 equals() 方法,但就是有人写了这样的代码,而且没有测试出来,发布了,而且在现场运行了一段时间之后才爆出了问题。

问题反思:问题是诡异之处在于,系统刚开始是正常的,经过一段时间的运行才出现问题。说明有什么东西发生了改变,而发生改变的东西显然不是代码本身,那到底是什么发生改变导致了这样诡异的的BUG呢?问题出在Integer本身。请看如下代码:

Integer a = 1;

Integer b = 1;

System.out.println(a.equals(b)); // true

System.out.println(a==b); // true

还有如下代码:

Integer a = 127;

Integer b = 127;

System.out.println(a.equals(b)); // true

System.out.println(a==b); // true

最后如下代码:

Integer a = 127+1;

Integer b = 127+1;

System.out.println(a.equals(b)); // true

System.out.println(a==b); // false   <<---

出现了诡异的  false ,而且数值定位在了 127+1,而这里到底发生了什么?为什么会出现这样的现象?

问题原因:我们使用Java自带的反编译工具对这段代码进行反编译,看看Java编译器对这段代码做了什么,命令行输入

javap -v  IntegerTest.class

跳过栈信息,输出如下:

反编译class文件

最重要的信息:

0: sipush        128

3: invokestatic  #16       // Method java/lang/Integer.valueOf(I)Ljava/lang/Integer;

6: astore_1

7: sipush        128

10: invokestatic  #16      // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

翻译一下:

Integer a = 127+1;  // Integer a = Integer.valueOf(128);

Integer b = 127+1; // Integer b = Integer.valueOf(128);

所以,看似你直接给 a 和 b 赋值 ,其实是编译器帮你做了一些事情,调用了 Integer.valueOf() 方法,而在Integer.valueOf()方法里面到底发生了什么呢?

Integer.valueOf()方法

IntegerCache 是什么?显然它是Java为了提高性能所做的一种缓存机制,缓存的下界是-128它是final的,默认的上界是127不是final的,JVM启动的时候就把这些值缓存起来了,看代码貌似上界是可以设置下界的值?

Integer.IntegerCache

当然可以改变缓存值的上界,为什么下界无法改变?可能是因为没必要吧,因为负数使用的频率确实很低不是么?JVM 启动参数决定缓存的上界大小。

而很显然,启动参数的名称没有写成 IntegerAutoBoxCacheMax,说明是全局的参数,奇怪的是看了下Long的源代码貌似并没有使用这个参数 ~_~ ,而是写死了-128~127

Long.LongCache

问题最终原因算是找到了,因为Java对小数值的Integer进行了缓存(使用频率高),以提高Java的效率,造成的现象就是在系统运行的起初阶段(包括测试阶段)在书记员id还很小的时候,== 的效果和equals一样,而后来随着id的不断增大(也可能书记员id不会超过127,问题就一直不暴露出来),达到128乃至更大的的时候,问题就必定暴露出来。

总结:当然这个坑算是填上了,在比较Integer/Long 等基本类型包装类是否相等的的时候的时候不要直接使用==去比较,而要使用equals方法。说的再笼统一点就是比较对象类型相等的时候请使用equals方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,572评论 18 399
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,693评论 0 11
  • 下面的内容是对网上原有的Java面试题集及答案进行了全面修订之后给出的负责任的题目和答案,原来的题目中有很多重复题...
    独念白阅读 1,320评论 0 3
  • 昨天太困了,吃了饭没一会儿就睡觉了。没写。昨天夸了一个小伙伴,其实就是简单两句,但看得出她挺“得意”,我也很“知足...
    灼灼其华529阅读 255评论 0 0
  • 在职场上,多想一步不仅意味着你躲开了一支箭,更意味着你掌握了主动权——闪老师坏心眼语录 小时候看过一个叫棋魂的动画...
    timshan阅读 598评论 12 4