Java基本類型-整型解讀

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類中有許多方法是和位操作相關的。待後續詳解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章