【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 類的介紹很簡單癞志,使用也一樣簡單簿寂,一般使用也不會出現(xiàn)什么問題,當(dāng)然文章標題既然是踩坑系列禽炬,就說說自己工作中遇到過的關(guān)于Integer的坑吧孩哑。


背景:上家公司是傳統(tǒng)行業(yè),所在的部門開發(fā)了一款法院庭審系統(tǒng),新版本發(fā)布前都經(jīng)過嚴格的測試(考慮到軟件的應(yīng)用現(xiàn)場是法院等一些國家單位基于數(shù)據(jù)保密性等的原因現(xiàn)場測試難度較大)蓝撇,由于從公司版本發(fā)布到真正軟件在現(xiàn)場環(huán)境運行可能是N個月之后,出現(xiàn)問題也難于排查陈莽,只能在公司環(huán)境進行復(fù)現(xiàn)渤昌,然后修改BUG。

問題出現(xiàn):軟件部署到現(xiàn)場走搁,經(jīng)過演示独柑,測試一切順利,法院開始使用私植,但是使用一段時間之后出現(xiàn)無法開庭的情況忌栅。

問題定位:進過調(diào)試,復(fù)現(xiàn)曲稼,最終問題定位在Integer比較相等的一段代碼上索绪。類似于下面的這段代碼:

if(userLogin.getId() == userSjy.getId()){ // 允許開庭 }

邏輯很簡單,就是當(dāng)前的用戶id和書記員id相等的時候允許開庭贫悄,否則不允許開庭瑞驱。而這里的User.id 的類型是Integer,或許你會說很明顯應(yīng)該用 equals() 方法窄坦,但就是有人寫了這樣的代碼唤反,而且沒有測試出來凳寺,發(fā)布了,而且在現(xiàn)場運行了一段時間之后才爆出了問題彤侍。

問題反思:問題是詭異之處在于肠缨,系統(tǒng)剛開始是正常的,經(jīng)過一段時間的運行才出現(xiàn)問題盏阶。說明有什么東西發(fā)生了改變晒奕,而發(fā)生改變的東西顯然不是代碼本身,那到底是什么發(fā)生改變導(dǎo)致了這樣詭異的的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 ? <<---

出現(xiàn)了詭異的 ?false ,而且數(shù)值定位在了 127+1蒸眠,而這里到底發(fā)生了什么漾橙?為什么會出現(xiàn)這樣的現(xiàn)象?

問題原因:我們使用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 賦值 淘捡,其實是編譯器幫你做了一些事情,調(diào)用了 Integer.valueOf() 方法池摧,而在Integer.valueOf()方法里面到底發(fā)生了什么呢焦除?

Integer.valueOf()方法

IntegerCache 是什么?顯然它是Java為了提高性能所做的一種緩存機制作彤,緩存的下界是-128它是final的膘魄,默認的上界是127不是final的,JVM啟動的時候就把這些值緩存起來了竭讳,看代碼貌似上界是可以設(shè)置下界的值创葡?

Integer.IntegerCache

當(dāng)然可以改變緩存值的上界,為什么下界無法改變绢慢?可能是因為沒必要吧灿渴,因為負數(shù)使用的頻率確實很低不是么?JVM 啟動參數(shù)決定緩存的上界大小胰舆。

而很顯然骚露,啟動參數(shù)的名稱沒有寫成 IntegerAutoBoxCacheMax,說明是全局的參數(shù)缚窿,奇怪的是看了下Long的源代碼貌似并沒有使用這個參數(shù) ~_~ 棘幸,而是寫死了-128~127

Long.LongCache

問題最終原因算是找到了,因為Java對小數(shù)值的Integer進行了緩存(使用頻率高)滨攻,以提高Java的效率够话,造成的現(xiàn)象就是在系統(tǒng)運行的起初階段(包括測試階段)在書記員id還很小的時候蓝翰,== 的效果和equals一樣光绕,而后來隨著id的不斷增大(也可能書記員id不會超過127女嘲,問題就一直不暴露出來),達到128乃至更大的的時候诞帐,問題就必定暴露出來欣尼。

總結(jié):當(dāng)然這個坑算是填上了,在比較Integer/Long 等基本類型包裝類是否相等的的時候的時候不要直接使用==去比較停蕉,而要使用equals方法愕鼓。說的再籠統(tǒng)一點就是比較對象類型相等的時候請使用equals方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末慧起,一起剝皮案震驚了整個濱河市菇晃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚓挤,老刑警劉巖磺送,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異灿意,居然都是意外死亡估灿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門缤剧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馅袁,“玉大人,你說我怎么就攤上這事荒辕『瓜” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵抵窒,是天一觀的道長弛针。 經(jīng)常有香客問我,道長估脆,這世上最難降的妖魔是什么钦奋? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮疙赠,結(jié)果婚禮上付材,老公的妹妹穿的比我還像新娘。我一直安慰自己圃阳,他們只是感情好厌衔,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捍岳,像睡著了一般富寿。 火紅的嫁衣襯著肌膚如雪睬隶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天页徐,我揣著相機與錄音苏潜,去河邊找鬼。 笑死变勇,一個胖子當(dāng)著我的面吹牛恤左,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搀绣,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼飞袋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了链患?” 一聲冷哼從身側(cè)響起巧鸭,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎麻捻,沒想到半個月后纲仍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡芯肤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年巷折,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崖咨。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡锻拘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出击蹲,到底是詐尸還是另有隱情署拟,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布歌豺,位于F島的核電站推穷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏类咧。R本人自食惡果不足惜馒铃,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痕惋。 院中可真熱鬧区宇,春花似錦、人聲如沸值戳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堕虹。三九已至卧晓,卻和暖如春芬首,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逼裆。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工郁稍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人波附。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓艺晴,卻偏偏與公主長得像昼钻,于是被迫代替她去往敵國和親掸屡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法然评,類相關(guān)的語法仅财,內(nèi)部類的語法,繼承相關(guān)的語法碗淌,異常的語法盏求,線程的語...
    子非魚_t_閱讀 31,599評論 18 399
  • Java8張圖 11、字符串不變性 12亿眠、equals()方法碎罚、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,697評論 0 11
  • 下面的內(nèi)容是對網(wǎng)上原有的Java面試題集及答案進行了全面修訂之后給出的負責(zé)任的題目和答案纳像,原來的題目中有很多重復(fù)題...
    獨念白閱讀 1,334評論 0 3
  • 昨天太困了荆烈,吃了飯沒一會兒就睡覺了。沒寫竟趾。昨天夸了一個小伙伴憔购,其實就是簡單兩句,但看得出她挺“得意”岔帽,我也很“知足...
    灼灼其華529閱讀 258評論 0 0
  • 在職場上玫鸟,多想一步不僅意味著你躲開了一支箭,更意味著你掌握了主動權(quán)——閃老師壞心眼語錄 小時候看過一個叫棋魂的動畫...
    timshan閱讀 602評論 12 4