1. 程式人生 > >JDK源碼解讀之Integer(1)

JDK源碼解讀之Integer(1)

java jdk 源碼 integer

本系列文章使用的JDK版本為jdk1.8.0_131,一些基礎的知識儲備:原碼、反碼、補碼,移位,建議參考文章:《原碼,反碼,補碼 詳解》《Java 源碼學習系列(三)——Integer》

Integer是我們開發過程中最常用的一個類,因此JDK的源碼解讀就從它開始吧。凡是對Java有點了解的都知道,Integer是int的包裝類型,長度為32位。因此我們可以看到如下定義

//可表示的最小值:-2^31,至於為什麽是這個數,上面的文章講的很清楚了
@Native public static final int   MIN_VALUE = 0x80000000;
//可表示的最大值:2^21-1
@Native public static final int   MAX_VALUE = 0x7fffffff;
//Integer是int的包裝類
public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int");

/**
 * 表示int使用多少位
 *
 * @since 1.5
 */
@Native public static final int SIZE = 32;

/**
 * 表示int使用多少字節,一個字節是8位
 *
 * @since 1.8
 */
public static final int BYTES = SIZE / Byte.SIZE;
/**
 * 存放int的值,final類型的,說明不可更改
 *
 * @serial
 */
private final int value;

/**
 * Integer構造方法,使用int
 */
public Integer(int value) {
    this.value = value;
}

/**
 * Integer構造方法,使用字符串,實際上把string轉為十進制int
 */
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
}

這個數組是幹嘛的呢?我們都知道數字是有0-9,十六進制使用了0-9和a-f(10-15),所以這個數組就是為了進行不同進制之間轉換時使用的常量數組,最小可以表示2進制,最大可以表示36進制(10個數字加26個字母)

final static char[] digits = {
    ‘0‘ , ‘1‘ , ‘2‘ , ‘3‘ , ‘4‘ , ‘5‘ ,
    ‘6‘ , ‘7‘ , ‘8‘ , ‘9‘ , ‘a‘ , ‘b‘ ,
    ‘c‘ , ‘d‘ , ‘e‘ , ‘f‘ , ‘g‘ , ‘h‘ ,
    ‘i‘ , ‘j‘ , ‘k‘ , ‘l‘ , ‘m‘ , ‘n‘ ,
    ‘o‘ , ‘p‘ , ‘q‘ , ‘r‘ , ‘s‘ , ‘t‘ ,
    ‘u‘ , ‘v‘ , ‘w‘ , ‘x‘ , ‘y‘ , ‘z‘
};

toString是怎麽樣實現的?

//i:待轉換的參數;radix:轉換的基數(多少進制)
public static String toString(int i, int radix) {
    //radix < 2 || radix > 36,則設置為10,為啥是36,因為上面有36個字符
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        radix = 10;

    /* 如果是十進制的話,使用下面的toString(int i) */
    if (radix == 10) {
        return toString(i);
    }
    //其實如果是十進制的話,也可以使用下面的方法,之所以沒有用就是出於效率的考慮

    char buf[] = new char[33];
    //如果是負數negative是true
    boolean negative = (i < 0);
    int charPos = 32;
        //如果不是負數,轉為負數統一處理
    if (!negative) {
        i = -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));
}
//把int按照十進制,轉為字符串
public static String toString(int i) {
    //如果i是最小值的話,直接返回
    if (i == Integer.MIN_VALUE)
        return "-2147483648";
    //獲取轉換後的字符串長度,如果是負數的話,需要符號為(-),所以返回的長度+1
    int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
    //定義相應長度的字符數組
    char[] buf = new char[size];
    //這個方法是關鍵,i待轉換的int參數,size轉換之後的字符串長度,buf字符數組
    getChars(i, size, buf);
    return new String(buf, true);
}

//這個數組是為了進行快速判斷長度定義的數組,分別代表1位,2位,超過9位,不超過最大值
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

// int轉為字符串的長度
static int stringSize(int x) {
    for (int i=0; ; i++)
        if (x <= sizeTable[i])
            //為啥是加1,因為數組下標i,代表的長度是i+1
            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‘,
    } ;

上面的兩個數組怎麽來的呢?看下面的數字矩陣,把十位數上的數字作為DigitTens數組,
個位數上的數字作為DigitOnes,是一樣的吧。
00 01 02 03 04 05 06 07 08 09 
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99


static void getChars(int i, int index, char[] buf) {
    int q, r;
    int charPos = index;
    char sign = 0;
    //如果是負數,定義符號位:-,之後把i轉換為正數處理
    if (i < 0) {
        sign = ‘-‘;
        i = -i;
    }

    // i大於65536時,一次生成兩位
    while (i >= 65536) {
        q = i / 100;
        // really: r = i - (q * 100);
        //q << 6相當於q*2^6,所以:q*2^6+q*2^5+q*2^2=q*(2^6+2^5+2^2)=q*100
        //為什麽用移位,不用上面的操作,效率問題
        r = i - ((q << 6) + (q << 5) + (q << 2));
        //說白了上面的幾部就是獲取余數r = i % 100;
        
        //i設置為i除以100的商
        i = q;
        
        //賦值,分別放到個位和十位上,以27為例:DigitOnes[27]=‘7‘,DigitTens[27]=‘2‘
        buf [--charPos] = DigitOnes[r];
        buf [--charPos] = DigitTens[r];
    }

    // Fall thru to fast mode for smaller numbers
    // assert(i <= 65536, i);
    for (;;) {
        //這裏和q = i / 10的效果一樣的,但是為什麽沒用呢?因為計算精度是夠用的,
        //2^19 = 524288,double s = 52429 / 524288 = 0.1000003814697266
        //為什麽是無符號右移(>>>),因為65536*52429溢出了
        q = (i * 52429) >>> (16+3);
        r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
        //上面幾部就是獲取余數 r = i % 10;
        buf [--charPos] = digits [r];
        i = q;
        if (i == 0) break;
    }
    //最後設置符號位
    if (sign != 0) {
        buf [--charPos] = sign;
    }
}


toUnsignedString是怎麽實現的?

//1、首先轉為無符號的long,然後調用Long的轉換方法
public static String toUnsignedString(int i, int radix) {
    return Long.toUnsignedString(toUnsignedLong(i), radix);
}

/**
int 轉為無符號long型,需要做到:高32位均為0,低32位等於這個int型參數的比特位,
非負的int轉為相等的long,負數轉為輸入值+2^32次方
*/
public static long toUnsignedLong(int x) {
    //0xffffffffL表示32個1,和x做‘與’操作,可以確保,高位為0,低位保持不變
    return ((long) x) & 0xffffffffL;
}
//該方法與上面的方法一樣,只不過是直接按照十進制去轉
public static String toUnsignedString(int i) {
    return Long.toString(toUnsignedLong(i));
}


int轉為不同進制的字符串表示

//轉為16進制的表示形式,為什麽是4,詳見下面formatUnsignedInt方法的實現;2^4 =16
public static String toHexString(int i) {
    return toUnsignedString0(i, 4);
}

//轉為八進制的表示形式,2^3 = 8
public static String toOctalString(int i) {
    return toUnsignedString0(i, 3);
}

//轉為二進制的表示形式,2^1 = 2
public static String toBinaryString(int i) {
    return toUnsignedString0(i, 1);
}

private static String toUnsignedString0(int val, int shift) {
    // assert shift > 0 && shift <=5 : "Illegal shift value";斷言為1-5
    //Integer.numberOfLeadingZeros(val);負數返回0,0返回32
    int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
    //如果mag=0的話,說明是0,chars=1;否則為(mag+(shift-1))/shift
    int chars = Math.max(((mag + (shift - 1)) / shift), 1);
    char[] buf = new char[chars];

    formatUnsignedInt(val, shift, buf, 0, chars);

    // Use special constructor which takes over "buf".
    return new String(buf, true);
}

/**
 * 在指定 int 值的二進制補碼表示形式中最高位(最左邊)的 1 位之前,返回零位的數量。
 * 如果指定值在其二進制補碼表示形式中不存在 1 位,換句話說,如果它等於零,則返回 32。 
 * 說白了就是找從左邊數0的個數,知道發現1為止,就是找第一個1的位置,
 * 負數返回0,因為負數的最高位為1
 * @since 1.5
 */
public static int numberOfLeadingZeros(int i) {
    // HD, Figure 5-6
    if (i == 0)
        return 32;
    int n = 1;
    //int是32位,為什麽是16、8、4、2,這是使用了二分查找方法
    //i先無符號右移16位,說明高16位位0,低16位位i的高16位,如果是0,說明i的前16位都是0,
    //然後i左移16位,左移之後,相當於i的高16位是之前的低16位,低十六位都是0
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    //判斷符號位n = n - i;
    n -= i >>> 31;
    return n;
}

static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
    int charPos = len;
    //基數,進制數=1 * 2^shift;這也是上面為什麽轉為16進制傳4,8進制傳3,二進制傳1的原因
    int radix = 1 << shift;
    int mask = radix - 1;
    do {
        //val & mask:為什麽會落在0-mask?
        //以16進制為例,那麽shift為4,那麽raidx=16,mask=15,15的二進制,補碼形式高位為0,
        //只有低4位為1;兩個數進行與操作,相當於保留了val的低4位
        buf[offset + --charPos] = Integer.digits[val & mask];
        //其實就是val = val / radix;
        val >>>= shift;
    } while (val != 0 && charPos > 0);

    return charPos;
}

parseInt的實現:把字符串根據進制數,轉為int

/**
 * 把字符串和進制數作為參數,轉為int
 *
 * <p>Examples:
 * <blockquote><pre>
 * parseInt("0", 10) returns 0
 * parseInt("473", 10) returns 473
 * parseInt("+42", 10) returns 42
 * parseInt("-0", 10) returns 0
 * parseInt("-FF", 16) returns -255
 * parseInt("1100110", 2) returns 102
 * parseInt("2147483647", 10) returns 2147483647
 * parseInt("-2147483648", 10) returns -2147483648
 * parseInt("2147483648", 10) throws a NumberFormatException
 * parseInt("99", 8) throws a NumberFormatException
 * parseInt("Kona", 10) throws a NumberFormatException
 * parseInt("Kona", 27) returns 411787
 * </pre></blockquote>
 *
 * @param      s   the {@code String} containing the integer
 *                  representation to be parsed
 * @param      radix   the radix to be used while parsing {@code s}.
 * @return     the integer represented by the string argument in the
 *             specified radix.
 * @exception  NumberFormatException if the {@code String}
 *             does not contain a parsable {@code int}.
 */
public static int parseInt(String s, int radix)
            throws NumberFormatException
{
    /*
     * 如果字符串是空,拋出異常
     */

    if (s == null) {
        throw new NumberFormatException("null");
    }

    //如果redix小於2,拋出異常
    if (radix < Character.MIN_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " less than Character.MIN_RADIX");
    }

    //如果redix大於36,拋出異常
    if (radix > Character.MAX_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " greater than Character.MAX_RADIX");
    }

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar < ‘0‘) { // 第一位可能是‘+’或者‘-’
            if (firstChar == ‘-‘) {
                //說明是負數,設置limit為Integer.MIN_VALUE
                negative = true;
                limit = Integer.MIN_VALUE;
            } else if (firstChar != ‘+‘)
                //如果不是‘+’,拋出異常
                throw NumberFormatException.forInputString(s);

            if (len == 1) // 不能只有一個‘+’或者‘-’
                throw NumberFormatException.forInputString(s);
            i++;
        }
        
        //如果是正數,limit為-Integer.MAX_VALUE,如果是正數limit為Integer.MIN_VALUE
        
        multmin = limit / radix;
        while (i < len) {
            //下面這段代碼,各種防止越界
            // 根據字符和進制獲取字符對應的int數值,後面會分析Character
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            }
            //避免result = result * radix越界,因為multmin已經是最小值了
            if (result < multmin) {
                throw NumberFormatException.forInputString(s);
            }
            result *= radix;
            //防止越界,result-digit < limit;
            //limit已經是最小值了,如果小於了,肯定發生了越界
            if (result < limit + digit) {
                throw NumberFormatException.forInputString(s);
            }
            result -= digit;
        }
    } else {
        //如果是空串,拋出異常
        throw NumberFormatException.forInputString(s);
    }
    //如果是負數,直接返回,否則轉為正數
    return negative ? result : -result;
}

/**
 * 調用上面的方法
 */
public static int parseInt(String s) throws NumberFormatException {
    return parseInt(s,10);
}

/**
 * 獲取無符號型int
 * @since 1.8
 */
public static int parseUnsignedInt(String s, int radix)
            throws NumberFormatException {
    if (s == null)  {
        throw new NumberFormatException("null");
    }

    int len = s.length();
    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar == ‘-‘) {
            throw new
                NumberFormatException(String.format("Illegal leading minus sign " +
                                                   "on unsigned string %s.", s));
        } else {
            //如果字符串長度不超過5位,或者是十進制,長度不超過9位,都可以用上面的方法去轉
            if (len <= 5 || // Integer.MAX_VALUE 使用36進制表示法是6位
                (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE 使用十進制表示法是10位
                return parseInt(s, radix);
            } else {
                //否則的話,轉為long
                long ell = Long.parseLong(s, radix);
                if ((ell & 0xffff_ffff_0000_0000L) == 0) {
                    return (int) ell;
                } else {
                    throw new
                        NumberFormatException(String.format("String value %s exceeds " +
                                                            "range of unsigned int.", s));
                }
            }
        }
    } else {
        throw NumberFormatException.forInputString(s);
    }
}

/**
 * 調用上面的方法
 * @since 1.8
 */
public static int parseUnsignedInt(String s) throws NumberFormatException {
    return parseUnsignedInt(s, 10);
}


Integer.valueOf()方法的實現:看了這個地方,就應該知道為什麽使用Integer.valueOf(int i)來創建Integer對象效率高了。

/**
 * 根據字符串和進制數,獲取一個Integer對象,調用Integer valueOf(int i)方法
 */
public static Integer valueOf(String s, int radix) throws NumberFormatException {
    return Integer.valueOf(parseInt(s,radix));
}

/**
 * 根據字符串,獲取一個Integer對象,默認采用十進制,調用Integer valueOf(int i)方法
 */
public static Integer valueOf(String s) throws NumberFormatException {
    return Integer.valueOf(parseInt(s, 10));
}

/**
 * Integer緩存,緩存的範圍是-128到127,在第一次使用的時候初始化
 * 可以通過-XX:AutoBoxCacheMax=<size>設置,在虛擬機初始化的時候,
 * 屬性java.lang.Integer.IntegerCache.high被設置保存在是有系統屬性中
 * 在sun.misc.VM類中
 */

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // 可以修改這個緩存的最大值
        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;
        //在初始化的時候把-128到127提前創建好
        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
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

hashCode和equals的實現:

/**
 * Integer的hashCode就是int的值(value)
 */
@Override
public int hashCode() {
    return Integer.hashCode(value);
}

/**
 * 返回value作為hashCode
 */
public static int hashCode(int value) {
    return value;
}

/**
 * equals,比較的是兩個intValue是否相等,
 */
public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

從系統屬性獲取Integer

/**
 * 從系統屬性文件中獲取int值,nm為屬性的key
 */
public static Integer getInteger(String nm) {
    return getInteger(nm, null);
}

/**
 * 從系統屬性文件中獲取int值,nm為屬性的key,val為默認值
 * 如果沒有key為nm的值,則返回val
 */
public static Integer getInteger(String nm, int val) {
    Integer result = getInteger(nm, null);
    return (result == null) ? Integer.valueOf(val) : result;
}

/**
 * 從系統屬性文件中獲取int值,nm為屬性的key,val為默認值
 */
public static Integer getInteger(String nm, Integer val) {
    String v = null;
    try {
        v = System.getProperty(nm);
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    if (v != null) {
        try {
            return Integer.decode(v);
        } catch (NumberFormatException e) {
        }
    }
    return val;
}
/**
 * 把字符串解析為Integer
 */
public static Integer decode(String nm) throws NumberFormatException {
    int radix = 10;
    int index = 0;
    boolean negative = false;
    Integer result;

    if (nm.length() == 0)
        throw new NumberFormatException("Zero length string");
    char firstChar = nm.charAt(0);
    // 判斷正負,如果有的話
    if (firstChar == ‘-‘) {
        negative = true;
        index++;
    } else if (firstChar == ‘+‘)
        index++;

    // 判斷進制
    if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
        index += 2;
        radix = 16;
    }
    else if (nm.startsWith("#", index)) {
        index ++;
        radix = 16;
    }
    else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
        index ++;
        radix = 8;
    }

    if (nm.startsWith("-", index) || nm.startsWith("+", index))
        throw new NumberFormatException("Sign character in wrong position");

    try {
        result = Integer.valueOf(nm.substring(index), radix);
        result = negative ? Integer.valueOf(-result.intValue()) : result;
    } catch (NumberFormatException e) {
        // If number is Integer.MIN_VALUE, we‘ll end up here. The next line
        // handles this case, and causes any genuine format error to be
        // rethrown.
        String constant = negative ? ("-" + nm.substring(index))
                                   : nm.substring(index);
        result = Integer.valueOf(constant, radix);
    }
    return result;
}

compareTo方法的實現:

/**
 * Integer對象的比較
 */
public int compareTo(Integer anotherInteger) {
    return compare(this.value, anotherInteger.value);
}

/**
 * 實際上是比較int值
 */
public static int compare(int x, int y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

/**
 * 無符號比較,
 */
public static int compareUnsigned(int x, int y) {
    return compare(x + MIN_VALUE, y + MIN_VALUE);
}

Integer中的一些位運算

/**
 * 
 * 獲取i的最高位的1,右邊補零,如果i是負數,返回Integer.MIN_VALUE;
 * 如果i是0,返回0;
 * 如果i是1,返回1;
 * 如果i是5,返回4;
 */
public static int highestOneBit(int i) {
    //假設i=5,則補碼為:00000000000000000000000000001001
    // i 和 (i >> 1)進行或操作,i = 00000000000000000000000000001101,
    //相當於從最高位開始的兩位為1
    i |= (i >>  1);
    //i = 00000000000000000000000000001111,相當於從最高位開始的四位為1
    i |= (i >>  2);
    //最高位1開始的前8位變為1,,因為i的最高位在第4位,因此右移四位,就是0,
    // 因此i不變,i = 00000000000000000000000000001111
    i |= (i >>  4);
    //最高位1開始的前16位變為1
    i |= (i >>  8);
    //最高位1開始的前32位變為1,i = 00000000000000000000000000001111
    i |= (i >> 16);
    //i >>> 1之後,i=00000000000000000000000000000111
    return i - (i >>> 1);
}

/**
 * 
 * 獲取i的最低位的1,右邊補零
 */
public static int lowestOneBit(int i) {
    // 正數:原碼,反碼,補碼一樣;負數:補碼為原碼的反碼+1,jvm中使用補碼,
    //所以,二者進行與操作,可得到最低位的1
    return i & -i;
}

/**
 * 最高位的1左邊的0的個數,負數返回0,如果是0,返回32
 * @since 1.5
 */
public static int numberOfLeadingZeros(int i) {
    // HD, Figure 5-6
    if (i == 0)
        return 32;
    int n = 1;
    //以i=5,即i=00000000000000000000000000001001
    //二分查找法,先查看高16位,如果是0,n = 1+ 16;i左移16位,即i的低十六位,變為高十六位
    //n = 1+16; i = 00000000000010010000000000000000
    if (i >>> 16 == 0) { n += 16; i <<= 16; }
    //n = 17 + 8; i = 00001001000000000000000000000000
    if (i >>> 24 == 0) { n +=  8; i <<=  8; }
    //n = 25+4; i = 10010000000000000000000000000000
    if (i >>> 28 == 0) { n +=  4; i <<=  4; }
    //i>>>30,不等於0
    if (i >>> 30 == 0) { n +=  2; i <<=  2; }
    //n = 29, i=10010000000000000000000000000000
    n -= i >>> 31;
    return n;
}

/**
 * 最低位1的最右邊的0的個數,如果是0,返回32
 * 和上面的方法類似,二分查找
 * @since 1.5
 */
public static int numberOfTrailingZeros(int i) {
    // HD, Figure 5-14
    int y;
    if (i == 0) return 32;
    int n = 31;
    y = i <<16; if (y != 0) { n = n -16; i = y; }
    y = i << 8; if (y != 0) { n = n - 8; i = y; }
    y = i << 4; if (y != 0) { n = n - 4; i = y; }
    y = i << 2; if (y != 0) { n = n - 2; i = y; }
    return n - ((i << 1) >>> 31);
}

/**
 * 二進制中1的個數
 * 
 * http://blog.csdn.net/cor_twi/article/details/53720640 
 *
 * @since 1.5
 */
public static int bitCount(int i) {
    // HD, Figure 5-2
    i = i - ((i >>> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
    i = (i + (i >>> 4)) & 0x0f0f0f0f;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    return i & 0x3f;
}




本文出自 “路飛的弟弟路癡” 博客,請務必保留此出處http://acesdream.blog.51cto.com/10029622/1969368

JDK源碼解讀之Integer(1)