問題一:
一直很好奇一件事,類似於Integer i = 15; String s = “aa”;之類的代碼是怎麼實現的?
Integer和String是一個類,i,s是對應的對象,對象的創建需要new出來(不討論反射),但是上面的對象怎麼創建的?
於是去找Integer的構造函數,在第849行找到了。。。(構造函數不都放在前面麼),如下:
private final int value;
public Integer(int value) {
this.value = value;
}
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
只此兩個構造函數,一個傳入int形參,一個傳入String形參。還是沒解決問題!按理說應該且必須類似於new Integer(10);這樣創建對象啊!!
於是在Integer類中搜索"new Integer("字樣。一共搜索到了兩處,一處在內部類IntegerCache中出現,一處在public static Integer valueOf(int i){}方法體中出現,並且該方法體中出現了IntegerCache內部類,更神奇的是內部類IntegerCache只在該方法體中出現,於是得出結論:該內部類就是爲該方法而創建。於是分析一下這個ValueOf(int i)方法:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
看到最後一個return語句,那肯定可以通過valueOf這個靜態方法創建對象,實驗一下果然成功了。
所以Integer只有兩種方式創建對象:直接創建和間接創建。①new Integer(10) ②Integer.valueOf(10)。開頭那種神奇的方法是用哪一種??
於是通過反編譯工具將代碼生成java文件後,神奇發現Integer i = 10變成了Integer i = Integer.valueOf(10);
所以問題解決了,編譯器將代碼處理成了valueOf方法去創建對象!!
問題二:
好像沒什麼問題了,想了想爲什麼編譯器不直接處理成new integer(10);上文可說了有兩種創建對象的方法,那個內部類是幹什麼用的?還專門爲valueOf(int i)方法創建一個內部類?
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
再看這個方法,只有i值在[IntegerCache.low, IntegerCache.high]範圍內纔會調用內部類創建對象,並且返回的是類成員變量cache數組的一個值,那這個數組裏面肯定就是存的對象咯。再看看這個內部類。
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() {}
}
讀完意思就是:類靜態變量cache存儲-128到127之間的Integer對象,靜態代碼塊已經初始化好了。
也就意味着valueOf(int i)中i在-128到127之間時,直接去cache中根據下標取對象就行,對象已經創建好了。
問題三:
那?這是何必呢?是不是還意味着Integer a = 10; Integer b = 10;後a和b是同一個對象呢?不知道。用==號實驗一下,果然,結果是ture!
那麼用意何在?
個人猜測是爲了避免反覆創建-128到127之間的相同對象吧。那。那也創建了256個對象?能節約內存?
常用方法:
① int轉Integer
public int intValue() {
return value;
}
② String轉Integer
//若字符串中有非數字則拋異常
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
③ Integer轉其他七個基本數據類型
public byte byteValue() {
return (byte)value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return value;
}
public long longValue() {
return (long)value;
}
public float floatValue() {
return (float)value;
}
public double doubleValue() {
return (double)value;
}
public String toString() {
return toString(value);
}