tft每日頭條

 > 科技

 > 有深意的代碼

有深意的代碼

科技 更新时间:2024-10-20 10:07:11

  關于Integer ,作為int 包裝類,新手經常會犯的錯誤是,比較兩個Integer 用 ==,作為有經驗的開發我們知道,包裝類、String 都應用用equals方法進行判斷。

  在實際項目中,我們經常會有枚舉值定義成Integer類型,有相當部分同學不注意,使用== 進行了比較,但是似乎又也沒怎麼出現Bug。這就不得不提起 Integer内部類 IntegerCache,它緩存了[-128,127] 的對象,這裡使用了享元模式,避免了對象的重複創建。

  因為枚舉值數量通常比較小,在[-128,127] 之間,代碼中也沒有誰變态到 new Integer(value),所以,許多場景使用的是 IntegerCache 緩存的對象,所以== 沒出現了問題。但不能說這麼用沒有錯,程序員要嚴謹,以防後續用到數值超過緩存的範圍,且不排除誰用new Integer 創建對象。

  雖然IntegerCache 不對外暴露,但是Java反射,可是神通廣大,如果用反射把一些緩存的值改掉,就會産生“有意思的”結果。下面代碼大家覺得輸出什麼

  Integer one = Integer.valueOf(1); Class iClass = Integer.class; Field valueField = iClass.getDeclaredField(value valueField.setAccessible(true); valueField.set(one,128); System.out.println((Integer)1 == 128);

  有深意的代碼(一段有意思代碼學習Integer)(1)

  輸出true

  其實這個涉及知識點不少,涉及Java 自動拆箱、Integer緩存

  左邊包裝類 右邊基本類型,會把左邊拆卸為基本類型,由于它的value 已經被改為128了,所以輸出true .

  但是上述代碼稍微修改下, 改為 Integer(1) == (Integer)128

  Integer one = Integer.valueOf(1); Class iClass = Integer.class; Field valueField = iClass.getDeclaredField(value valueField.setAccessible(true); valueField.set(one,128); System.out.println((Integer)1 == (Integer)128);

  有深意的代碼(一段有意思代碼學習Integer)(2)

  結果就為false。

  因為上面代碼兩個Integer 類型,比較是不是同一個對象,顯然128不在緩存中,

  如果把128 改為緩存範圍内一個數呢,如下,結果也會為false。

  public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Integer one = Integer.valueOf(1); Class iClass = Integer.class; Field valueField = iClass.getDeclaredField(value valueField.setAccessible(true); valueField.set(one,3); System.out.println((Integer)1 == (Integer)3); }

  有深意的代碼(一段有意思代碼學習Integer)(3)

  學C 的,估計第一次接觸這個要吐血了,既然說了順便複習下Integer 類型值默認null ,int 默認值0。這個IntgerCache 确實饒了點。

  同樣的Long 也有類似的Cache,值得一提的是redis 中有類似的緩存,隻是範圍不一樣,編程複雜度與空間開銷方面,如果是我會選擇簡單,期待jdk某個版本會把它幹掉。

  講完,後面持續輸出

  ,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved