日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LongCache机制与Long等值比较\\\\Integer 中的缓存类IntegerCache

發(fā)布時間:2024/2/28 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LongCache机制与Long等值比较\\\\Integer 中的缓存类IntegerCache 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)載自https://www.cnblogs.com/wellmaxwang/p/4422855.html

https://blog.csdn.net/louistech/article/details/51062966



一、背景引入
近期在開發(fā)一個項目的后臺時,當項目上線后出現(xiàn)了一個測試環(huán)境沒有出現(xiàn)的問題:部分用戶在提交信息時提示了該信息不屬于當前用戶。
經(jīng)過對代碼的review,發(fā)現(xiàn)了出錯的代碼的開發(fā)邏輯是,在用戶提交信息之后,將信息更新入數(shù)據(jù)庫之前,首先判斷當前的信息是否屬于當前的用戶;通過信息.account_id == 用戶.id進行了判斷,兩個id都是Long類型。直覺是使用==號出錯的問題,于是將此處的代碼修改為先使用Long.longValue()取出來,再進行比較。(或者使用Long.equals()方法亦可)
然而有一個相當有趣的情況,那就是測試環(huán)境并沒有這樣的問題。究其原因,竟是因為Long類型的LongCache機制引起,且因為測試環(huán)境的模擬用戶數(shù)據(jù)量較少,沒有突破LongCache內(nèi)部緩存數(shù)組的邊界,導致該問題沒能及時在測試環(huán)境發(fā)現(xiàn)。


二、編程建議

在Java開發(fā)過程中,最好嚴格區(qū)分原始類型(long/int/short/...)和封裝類型(Long/Integer/Short...),雖然JDK能夠在大多數(shù)情況下進行智能的轉(zhuǎn)型,但是當面對開發(fā)一個涉及到金錢的項目時,這樣的風險仍然太大!

Java在數(shù)據(jù)封裝類型的設計中,都帶了.equals()方法。


三、模擬

1、程序1

[java]?view plaincopy
  • public?class?A?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????Long?l1?=?128L;??
  • ????????Long?l2?=?128L;??
  • ????????System.out.println(l1?==?l2);???
  • ????}??
  • }??

  • 程序輸出:false

    2、程序2

    [java]?view plaincopy
  • public?class?A?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????Long?l1?=?127L;??
  • ????????Long?l2?=?127L;??
  • ????????System.out.println(l1?==?l2);???
  • ????}??
  • }??

  • 程序輸出:true


    三、關(guān)于LongCache.class

    在Long的源代碼中,可以找到LongCache內(nèi)部類的代碼:

    [java]?view plaincopy
  • private?static?class?LongCache?{??
  • ????????private?LongCache(){}??
  • ??
  • ????????static?final?Long?cache[]?=?new?Long[-(-128)?+?127?+?1];??
  • ??
  • ????????static?{??
  • ????????????for(int?i?=?0;?i?<?cache.length;?i++)??
  • ????????????????cache[i]?=?new?Long(i?-?128);??
  • ????????}??
  • ????}??

  • 從LongCache的代碼可以很容易看出來,在類初始化的時候,便生成了一個final的static的Long類型數(shù)組,數(shù)組的范圍是-128到127。

    Long類型的valueOf方法代碼如下:

    [java]?view plaincopy
  • public?static?Long?valueOf(long?l)?{??
  • ????????final?int?offset?=?128;??
  • ????????if?(l?>=?-128?&&?l?<=?127)?{?//?will?cache??
  • ????????????return?LongCache.cache[(int)l?+?offset];??
  • ????????}??
  • ????????return?new?Long(l);??
  • ????}??
  • 從以上兩個代碼中不難發(fā)現(xiàn),當外部程序調(diào)用了valueOf方法時,Java先判斷欲生成的Long對象是否在LongCache.cache數(shù)組的范圍內(nèi),如果是,則直接返回已經(jīng)存在cache數(shù)組的Long對象引用。根據(jù)之前對String類型的研究,這應該是通過重復使用對象的引用,從而實現(xiàn)了較高的性能和較少的內(nèi)存消耗。此外,經(jīng)過測試,通過“Long = long”方式生成的Long對象,稱為自動封箱,也有相同的邏輯。
    所以也就不難知道,當實際的long大小超過正數(shù)127時,判斷兩個封裝類==時,會返回false。

    另外一種情況,通過new方式生成的兩個等值的對象,是否會有相同的效果呢?經(jīng)過測試,是否定的。兩次new出來的對象,都是在內(nèi)存中新劃分區(qū)域生成的對象,除非重寫方法,否則是絕對不能通過==進行比較的。



    四、其他內(nèi)容

    1、Integer、Short、Character、Bytes等封裝類也有類似的機制;

    2、請關(guān)注JVM參數(shù):AutoBoxCacheMax

    3、請關(guān)注Integer內(nèi)部類IntegerCache的high屬性。


    ———————————————————————————————————————————————————

    2014年去某公司筆試的時候遇到這么一道題:

    public class Test {public static void main(String[] args) {Integer int1 = Integer.valueOf("100");Integer int2 = Integer.valueOf("100");System.out.println(int1 == int2);} }

    問打印的結(jié)果的多少? 但是我回答的是false, 后來仔細想想應該沒有這個簡單,就翻了下JDK的源碼,發(fā)現(xiàn):

    public static Integer valueOf(String s) throws NumberFormatException {return Integer.valueOf(parseInt(s, 10));}public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

    發(fā)現(xiàn)里面另有玄機,多了個IntegerCache類:

    private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it. }}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}

    原來Integer把-128到127(可調(diào))的整數(shù)都提前實例化了。 這就解釋了那道面試題的答案,原來你不管創(chuàng)建多少個這個范圍內(nèi)的Integer用ValueOf出來的都是同一個對象。

    但是為什么JDK要這么多此一舉呢? 我們仔細想想, 淘寶的商品大多數(shù)都是100以內(nèi)的價格, 一天后臺服務器會new多少個這個的Integer, 用了IntegerCache,就減少了new的時間也就提升了效率。同時JDK還提供cache中high值得可配置,

    這無疑提高了靈活性,方便對JVM進行優(yōu)化。

    ?

    參考Long的源碼:

    private static class LongCache {private LongCache(){}static final Long cache[] = new Long[-(-128) + 127 + 1];static {for(int i = 0; i < cache.length; i++)cache[i] = new Long(i - 128);}}

    Long也做了緩存,只是沒有提供調(diào)整機制, 在Short中類似:

    private static class ShortCache {private ShortCache(){}static final Short cache[] = new Short[-(-128) + 127 + 1];static {for(int i = 0; i < cache.length; i++)cache[i] = new Short((short)(i - 128));}}

    總結(jié)

    以上是生活随笔為你收集整理的LongCache机制与Long等值比较\\\\Integer 中的缓存类IntegerCache的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。