1. 程式人生 > 實用技巧 >Java資料型別之Cache模式

Java資料型別之Cache模式

1、關於Java資料型別

基本資料型別

基本資料型別有8種,每種基本資料型別都有對應的引用型別。

型別 描述 長度 可表示資料 包裝型別
boolean 布林型 1 true、false Boolean
byte 位元組型 1 2-7~27-1 Byte
char 字元型 2 2-15~215-1 Character
short 短整型 2 2-15~215-1 Short
int 整型 4 2-31~231-1 Integer
float 浮點型 4 2-31~231-1 Float
long 長整型 8 2-63~263-1 Long
double 雙精度浮點型 8 2-63~263-1 Double

為什麼要有包裝型別?

因為Java是面嚮物件語言,很多地方用到的是物件,而不是基本資料型別。比如集合類中,我們是無法定義集合的泛型是基本資料型別的。而包裝類,顧名思義,就是將基本資料型別包裝起來,使其具備了物件的性質,也為其添加了很多操作方法。

自動裝箱與拆箱

自動裝箱: 就是將基本資料型別自動轉換成對應的包裝類。

自動拆箱:就是將包裝類自動轉換成對應的基本資料型別。

為什麼要有自動裝拆箱呢?因為很多地方都是需要其進行轉換的,而重複操作又會顯得很多餘,所以為其提供了自動適配功能。

那麼哪些地方能用到呢?舉兩個最常用的例子。

  1. 型別轉換
Integer i = 10; // 自動裝箱
int a = i; // 自動拆箱

2)存入集合

List<Integer> list = new ArrayList<Integer>();
int a = 1;
list.add(a); // 自動裝箱

2、Cache

顧名思義,Cache就是快取的意思。那資料型別裡面哪些地方用到Cache呢?它具備什麼作用?

首先丟擲一道題,請大家參考。

Integer a = Integer.valueOf(20);
Integer b = Integer.valueOf(20);
System.out.println(a == b);

結果相等嗎?是相等的。輸出true。

Integer a = Integer.valueOf(128);
Integer b = Integer.valueOf(128);
System.out.println(a == b);

這裡結果不相等的,為啥?128!=128?

首先來看valueOf這個方法:

  • Integer valueOf(String s, int radix)

將字串以規定進位制轉換成Integer,radix表示進位制數。

  • Integer valueOf(String s)

將字串轉換為10進位制的Integer。

  • Integer valueOf(int i)

將基本資料型別轉換為包裝類。

為什麼會造成兩個相同數字比較出來不相同呢?來,我們上原始碼。

前兩個方法最終呼叫的方法:

    public static Integer valueOf(int i) {
        // 如果值在IntegerCache的低位和高位之間就從IntegerCache裡取
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        // 否則new一個物件
        return new Integer(i);
    }

IntegerCache是Integer中的一個靜態內部類

private static class IntegerCache {
        // 低位固定為-128
        static final int low = -128;
        // 高位
        static final int high;
        // 存放快取區資料
        static final Integer cache[];

        static {
            // 高位預設為127
            int h = 127;
            // 可以通過配置
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    // 將配置值轉換為基本資料型別
                    int i = parseInt(integerCacheHighPropValue);
                    // 將配置值與127比較取最大值
                    i = Math.max(i, 127);
                    // 確定高位值,防止陣列長度超過整型最大值
                    h = 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)
            // 如果高位值大於等於127,則丟擲異常
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

因為128超過了整型快取區域,所以每次都會new一個物件,所以導致比較出來不相等。

Short、Long、Character等內部都有Cache區域,建議大家多去挖掘挖掘。