java的基本類型包括以下幾類:
- 整型 byte short int long
- 浮點型 float double
- 字符型 char
- 布爾型 boolean
它們都有對應的包裝類型(如果沒有特殊說明,下面都是說包裝類型),其中整型和浮點型的基類都是Number,並且都是現實了Comparable接口,下面的內容以Integer爲例,Byte,Short,Integer,Long只有整型長度上的區別,其他都是類似的。
Integer內部結構
類的內部數據結構是很簡單的,只是簡單包含了一個基本類型數據,並且提供了一些對基本類型的常見操作。
public final class Integer extends Number implements Comparable<Integer> {
//more code...
/**
* The value of the <code>Integer</code>.
*
* @serial
*/
private final int value;
//more code...
}
Integer的hashCode、equals和Comparable接口
Integer實現了Comparable接口,內部只是簡單使用value值進行比較。還實現了hashCode和equals方法,不過equals還是會進行類型的對比,這也是equal實現的一個基本原則。所以Integer和Long是無論如何都不會相等的。
public int hashCode() {
return value;
}
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Integer內部緩存對象
或許你看過一些面試題,使用==來比較進行包裝類型的比較,有時候會返回true,這有點不合常理。這個可以通過源碼來解釋。以Integer它在內部預先定義了一小段Integer對象(見IntegerCache的實現,high的範圍還可以通過系統參數java.lang.Integer.IntegerCache.high設置),並在valueOf調用時判斷是否落在這個範圍,如果範圍合適,返回現成的對象。由於Integer是不變對象,所以它的複用是沒有任何隱患的。
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
話雖如此,但這只是一個優化手段,平時是不應該使用==來進行判斷對象是否相等的。
Integer和字符串的相互轉換
整型和字符串的相互轉換也是常用的功能。看一下Integer轉換成字符串的源碼。
public static String toString(int i, int radix) {
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
/* Use the faster version */
if (radix == 10) {
return toString(i);
}
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
if (!negative) {
i = -i;
}
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (33 - charPos));
}
算法還是比較簡單的,就是根據基數radix不斷對這個整數取餘數,根據餘數找到從digits數組中找到對應字符。這裏需要注意的是,
爲什麼正數要取反使用負數而不是反過來呢,用正數不是更好處理麼?其實,這涉及到是否溢出的問題,對於最小的整數integer,取反就會出現移除,還是一個負數,這樣就有問題了。
還有一個功能是把整數換成16進制(toHexString)、8進制(toOctalString)或2進制的字符串(toBinaryString),它最終是調用toUnsignedString實現的。
/**
* Convert the integer to an unsigned number.
*/
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
以16進製爲例子,shift就是4,得到的mark就是1111,i和mask做與運算後就可以得到在16進制中字符數組的位置,從而得到這4位對應的16進制字符,最後通過右移就抹掉這低4位。
Integer類中有許多方法是和位操作相關的。待後續詳解。