本文來聊一下Integer中的兩個常用的靜態(tài)方法valueOf和parseInt绸狐,順便引出基本類型包裝類的緩存策略
前言
這篇文章的想法來源于一次代碼檢查,使用findbugs插件檢查代碼础倍,然后報了如下信息(不屬于bug,但是是一個更好的建議)
A boxed primitive is created from a String, just to extract the unboxed primitive value. It is more efficient to just call the static parseXXX method.
大致意思就是說把String類型轉(zhuǎn)換成了包裝類挪哄,而參數(shù)需要的是基本類型值私沮,所以用parseXXX方法更有效移怯。說實話這些方法很常用香璃,也比較簡單,就沒有去看過它們到底有什么區(qū)別舟误,直到這次偶然的機會增显。
源碼分析
先來看下面這兩個方法
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);
}
可以看到將字符串類型轉(zhuǎn)換為Integer對象實則就是先去調(diào)用了parseInt(String s, int radix)方法,轉(zhuǎn)換為int基本類型后脐帝,再包裝為Integer對象。
看到這里其實就已經(jīng)解釋了上述findbugs的問題糖权,但是可以發(fā)現(xiàn)堵腹,valueOf方法中先進行了范圍判斷,通過 IntegerCache 這個類名我們可以知道星澳,這里做了緩存疚顷。
接下來先做個無獎競猜,猜猜下面兩行分別輸出什么
System.out.println(Integer.valueOf(100) == Integer.valueOf(100));
System.out.println(Integer.valueOf(200) == Integer.valueOf(200));
相信即使不熟悉的同學看到這里也必然知道有坑哈哈禁偎,結(jié)果自己驗證下就曉得了
那么就來看下 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 property
int 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_VALUE
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)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
Integer中默認緩存范圍為-128~127腿堤,新建一個數(shù)組,通過for循環(huán)緩存范圍內(nèi)的Integer對象如暖。
緩存最大值是可以通過設置
-Djava.lang.Integer.IntegerCache.high=xxx
來進行修改笆檀,該緩存會在首次使用Integer時初始化。
說到底這里做緩存是為了節(jié)省內(nèi)存盒至,提高性能酗洒,默認-128~127的范圍是因為該范圍內(nèi)的數(shù)字使用頻率較高士修。
那么既然Integer類有緩存,其他基本類型的包裝類是否也做了緩存呢樱衷?
去看一下其他包裝類的代碼棋嘲,答案是肯定的
Byte Short Long Character 都做了緩存,前三個范圍固定都是-128~127
Character 緩存范圍為0~127
并且只有IntegerCache的緩存范圍可配置