1. 程式人生 > >Java原始碼之路---基礎資料型別

Java原始碼之路---基礎資料型別

Java原始碼基礎資料型別

1、Java與數先關的基礎資料型別主要分整數與浮點數,整數:byte,short,int,long,浮點數:float,double

2、資料範圍

型別 範圍
byte -128~127(2^7-1)
short -32768~32767(2^15-1)
int -2147483648~2147483647(2^31-1)21億(10位)
long -9223372036854775808~9223372036854775807(2^63-1)19位
float +/-2^−149,+/-2^128
double +/-2^−1074,+/-2^1024

3、六個型別均繼承自Number,Number類為抽象類

public abstract class Number implements java.io.Serializable {
    public abstract int intValue();
    public abstract int longValue();
    public abstract int floatValue();
    public abstract int doubleValue();
    public byte byteValue
() { return (byte)intValue(); } public short shortValue() { return (short)intValue(); } }

4、整數的byte、short、int、long對於的封裝類,都有相關的快取操作,具體實現是通過內部類

    private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127
+ 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Long(i - 128); } }

Byte對應ByteCache,Integer對應IntegerCache,Short對應ShortCache,Long對應LongCache,它們的快取範圍都是從-128~127。其中IntegerCache提供了可通過屬性設定“java.lang.Integer.IntegerCache.high”設定快取的最大值。

舉個有趣的栗子

        Integer c = 3;
        Integer d = 3;
        int e = 321;
        Integer g = 321;
        Integer h = 321;

        // 使用了快取
        System.out.println(c == d); // true

        System.out.println(e == g); // true

        System.out.println(h == g); // false

5、都提供了不同進位制的數表示

6、toString()

    public static String toString(int i) {
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        // 1、獲取數的位數
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        // 2、int轉化成char[]陣列
        getChars(i, size, buf);
        return new String(buf, true);
    }
    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };
    // 
    // Requires positive x
    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }
    final static char [] DigitTens = {
        '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
        '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
        '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
        '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
        '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
        '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
        '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
        '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
        '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
        '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
        } ;

    final static char [] DigitOnes = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        } ;

    static void getChars(int i, int index, char[] buf) {
        int q, r;
        int charPos = index;
        char sign = 0;

        if (i < 0) {
            sign = '-';
            i = -i;
        }

        // Generate two digits per iteration
        while (i >= 65536) {
            q = i / 100;
            // really: r = i - (q * 100);
            r = i - ((q << 6) + (q << 5) + (q << 2));
            i = q;
            buf [--charPos] = DigitOnes[r];
            buf [--charPos] = DigitTens[r];
        }

        // Fall thru to fast mode for smaller numbers
        // assert(i <= 65536, i);
        for (;;) {
            // q = i / 10
            q = (i * 52429) >>> (16+3);
            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
            buf [--charPos] = digits [r];
            i = q;
            if (i == 0) break;
        }
        if (sign != 0) {
            buf [--charPos] = sign;
        }
    }
關鍵點
移位的效率比直接乘除的效率要高
乘法的效率比除法的效率要高
通過查詢陣列,實現快速訪問,避免除法計算
重複利用計算結果:在獲取r(i%100)時,充分利用了除法的結果,結合位移避免重複計算。
位運算
負數的補碼:符號位:1,其餘絕對值的原碼按位取反+1
按位與(&)
按位或(|)
按位非(~)
按位異或(^):相同為0,不同為1,異或0具有保持的特點,而異或1具有翻轉的特點
左位移(<<)理解為乘法,如900 << 6 : 900 * 2 ^ 6 = 900 * 64
右位移(>>)理解為除法, 如900 >> 6 : 900 / 2 ^ 6 = 900 / 64
無符號右移(>>>)

7、浮點數(實現的原始碼:FloatingDecimal),如要進行精確的運算,要使用BigDecimal