衆所周知Long中有個小小的陷阱,就是在-128至127範圍內,Long.valueOf(long l)返回的Long的實例是相同的,而在此範圍以外每次使用valueOf(long l)時,返回的實例都是不一樣的。本篇文章的主要目的就是揭示這個小陷阱。java
首先來看一段代碼,驗證上述的小陷阱。
程序員
System.out.println(Long.valueOf(128) == Long.valueOf(128)); System.out.println(Long.valueOf(127) == Long.valueOf(127));
輸出結果: false true
像變魔術同樣,揭開以後就會以爲異常簡單。這裏也是一樣的道理。上兩段代碼,明白人一看便知。
數組
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); } }
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); }
其實在Long中有一個靜態的內部類LongCache,專門用於緩存-128至127之間的值。說到這裏,不得不讚美一下寫這個方法的做者,很是很是用心啊,看看cache這個數組的長度:-(-128) + 127 + 1.就是想告訴閱讀這段代碼的人,我是從-128開始,正數最大爲127,而後後面的1表明數字0。一共256個元素。緩存
若是僅僅是緩存下來而不去使用那麼就沒有任何意義。valueOf(long l)就是使緩存派上用場的方法,它會判斷傳入的參數是否在-128-127之間,若是是則直接從緩存中返回對應的引用,不然新建立一個Long的實例。valueOf這個方法我以爲比較好的一處是offset,它的初始值設爲128,仔細想一想,cache128其實存放的是0,這樣就將正數和負數分隔開,並且針對-128-127之間的任何數做爲參數傳入都不須要作任何特殊處理,只要返回LongCache.cache(int)l + offset;便可,正負通吃。spa
程序員真的好奇怪,每當看到精巧的代碼時,都會有種賞心悅目的感受。我喜歡Long這個類,到處是寶!.net