從java 5開始,基礎數據類型被賦予了自動裝箱和自動拆箱機制。
打印結果為true,false
這是為什么呢?
這是由于Integer在自動裝箱過程中使用了緩存機制。
基礎數據類型在自動裝箱過程中會使用緩存機制來提高效率,在緩存范圍內相同值的自動裝箱對象相同(==為true),本文將總結基礎數據類型在自動裝箱過程中的緩存特點。
話不多說,先上結果:
類型 | 字節數 | 包裝類型 | 緩存范圍 | 說明 |
---|---|---|---|---|
byte | 1 | Byte | -128 ~ 127 | 全部緩存 |
short | 2 | Short | -128 ~ 127 | 部分緩存 |
int | 4 | Integer | -128 ~ 127 | 部分緩存最大值默認為127可以通過設定JVM啟動參數-XX:AutoBoxCacheMax=<size> 來修改緩存的最大值 |
long | 8 | Long | -128 ~ 127 | 部分緩存 |
char | 2 | Character | 0 ~ 127 | 部分緩存 |
boolean | 1或4 | Boolean | true, false | 全部緩存boolean類型在編譯后使用java虛擬機的int數據類型代替,boolean數組則被編碼為byte數組 |
float | 4 | Float | 沒有緩存 | |
double | 8 | Double | 沒有緩存 |
我們知道,在自動裝箱過程中,使用了對應包裝類的valueOf
靜態方法
例如:Integer num = 100;
等價于Integer num = Integer.valueOf(100);
Integer中自動裝箱使用的valueOf函數定義如下:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }可以看到在IntegerCache.low ~ IntegerCache.high之間的數字,將會從緩存中獲取,在這個區間之外的數字,將創建一個新的Integer對象。 接下來再來看看IntegerCache的定義(它是定義在Integer內部的一個靜態類):
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the -XX:AutoBoxCacheMax=<size> option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {}}通過代碼及注釋,我們可以了解到以下幾點信息:
在IntegerCache中定義了一個Integer數組cache
在first usage(IntegerCache類被加載)時進行初始化其緩存范圍默認為從-128至127可以通過-XX:AutoBoxCacheMax=<size>
來控制cache
的size
所以,在默認情況下,-128~127范圍內的自動裝箱使用了緩存,相同的值自動裝箱后的對象相同(即a == b 為true)。
延伸閱讀: 為什么java中要做IntegerCache這種設置?
byte/short/long對應的包裝類的緩存方式與Integer不同,沒有用到自定義Cache類,而是直接在包裝類內部定義了一個長度為256的緩存數組:
char的包裝類型Character的自動裝箱緩存方式類似于byte/short/long,不過緩存長度只有128(0~127)
public static Character valueOf(char c) { return c < 128 ? SMALL_VALUES[c] : new Character(c);}private static final Character[] SMALL_VALUES = new Character[128];static { for (int i = 0; i < 128; i++) { SMALL_VALUES[i] = new Character((char) i); }}boolean只有2個值:true和false,在源碼中valueOf方法使用了2個常量來進行自動裝箱
public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE;}float和double都屬于浮點型,自動裝箱沒有使用緩存,任何相同的值自動裝箱后用==來判斷都會返回false
在使用基礎數據類型時,我們需要注意自動裝箱及自動拆箱的影響。特別是在使用==來進行判斷的時候要注意自動裝箱的緩存
新聞熱點
疑難解答