天天看點

[Java開發之路](19)Long緩存問題

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/SunnyYoona/article/details/50849573

Long中有個小小的陷阱,就是在-128至127範圍内,Long.valueOf(long l)傳回的Long的執行個體是相同的,而在此範圍之外每次使用valueOf(long

l)時,傳回的執行個體都是不同的。

舉例:

  1. System.out.println(Long.valueOf(-129) == Long.valueOf(-129)); // false

  2. System.out.println(Long.valueOf(-128) == Long.valueOf(-128)); // true

  3. System.out.println(Long.valueOf(127) == Long.valueOf(127)); // true

  4. System.out.println(Long.valueOf(128) == Long.valueOf(128)); // false

下面我們通過Long源碼進行分析一下:

  1. public static Long valueOf(long l) {

  2. final int offset = 128;

  3. if (l >= -128 && l <= 127) { // will cache

  4. return LongCache.cache[(int)l + offset];

  5. }

  6. return new Long(l);

  7. }

從上面代碼中我們可以看出先判斷傳遞過來的數值是否在[-128,127]之間,如果是則直接從緩存中傳回對應的引用,否則新建立一個Long的執行個體。是以說如果不在這個區間範圍内,傳回一個新建立的Long類型引用,用==判斷就會理所當然的傳回false,位址不一樣。但是如果我們使用equals方法,則會傳回true,數值是一樣的。

  1. Long.valueOf(128).equals(Long.valueOf(128)) // true

我們看看對于在區間範圍之内,是如何傳回對應的引用?最重要的是Long類中有一個靜态的内部類LongCache,專門用于緩存-128至127之間的值。

  1. private static class LongCache {

  2. private LongCache(){}

  3. static final Long cache[] = new Long[-(-128) + 127 + 1];

  4. static {

  5. for(int i = 0; i < cache.length; i++)

  6. cache[i] = new Long(i - 128);

  7. }

  8. }

在LongCache類中定義了一個cache數組,來存儲緩存資料。我們可以看到cache數組的長度:-(-128) + 127 + 1,很明了的知道緩存資料從-128到127,後面的1代表數字0,一共256個元素。

valueOf這個方法設計比較好的一點是offset,它的初始值設為128,目的就是為了數組下标128處存放0,這樣就将正數和負數分隔開。