java Integer源码分析

一、常见方法

1、public static String toString(int i)

返回一个表示指定整数的 String 对象。将该参数转换为有符号的十进制表示形式,以字符串形式返回它,就好像将参数和基数 10 作为参数赋予 toString(int, int) 方法。
参数:
i - 要转换的整数。
返回:
十进制(基数 10)参数的字符串表示形式。
源码:
 ======================Integer.class============================
    @HotSpotIntrinsicCandidate
    public static String toString(int i) {
        // 数字长度
        int size = stringSize(i);
        //  紧凑的空间布局(COMPACT_STRINGS),LATIN1单字节编码,UTF16双字节编码
        if (COMPACT_STRINGS) {
            byte[] buf = new byte[size]; // 单字节编码,一个字节存储一个数字
            getChars(i, size, buf);
            return new String(buf, LATIN1);
        } else {
            byte[] buf = new byte[size * 2]; // 双字节编码,两个字节存储一个数字
            StringUTF16.getChars(i, size, buf);
            return new String(buf, UTF16);
        }
    }
    ==================Integer.class=======================
    // int类型数字位数
    // int类型范围[-2147483648, 2147483647]
    // 最高10位数。
    // 正数长度最高是10,负数长度最高是11(比正数多一位负号)
    static int stringSize(int x) {
        int d = 1;
        if (x >= 0) {
            d = 0;
            x = -x;
        }
        int p = -10;
        for (int i = 1; i < 10; i++) {
            if (x > p)
                return i + d;
            p = 10 * p;
        }
        return 10 + d;
    }
    ================Integer.class========================
    static int getChars(int i, int index, byte[] buf) {
        int q, r;
        int charPos = index;

        boolean negative = i < 0;
        // 转为负数参加下面的计算
        if (!negative) {
            i = -i;
        }

        // Generate two digits per iteration
        // 每次迭代生成两位数,并通过两个字符数组DigitOnes、DigitTens获取十位数和个位数所对应的字符。
        // 从后到前填充buf。
        while (i <= -100) {
            q = i / 100;
            // 取出该数字的最低两位
            r = (q * 100) - i;
            i = q;
            // 个位对应的字符
            buf[--charPos] = DigitOnes[r];
            // 十位对应的字符
            buf[--charPos] = DigitTens[r];
        }

        // We know there are at most two digits left at this point.
        // 经过前面的迭代后,0 > i > -100,
        q = i / 10;
        // 取数字i的个位(i可能是两位数或个位数)
        r = (q * 10) - i;
        // 通过偏移量r取数字r对应的字符'r'
        buf[--charPos] = (byte)('0' + r);

        // Whatever left is the remaining digit.
        // 如果前面的i是两位数,则q是i的十位数,且q<0
        // 如果前面的i是一位数,则q==0,q为0则不用将q放入buf
        if (q < 0) {
            buf[--charPos] = (byte)('0' - q); //q为负数,计算绝对值|q|对应的'q'时用'0'-q。
        }

        // 若是负数,加上负号
        if (negative) {
            buf[--charPos] = (byte)'-';
        }
        return charPos;
    }
    ======================StringUTF16.class=======================================
    static int getChars(int i, int index, byte[] buf) {
        int q, r;
        int charPos = index;

        boolean negative = (i < 0);
        if (!negative) {
            i = -i;
        }

        // Get 2 digits/iteration using ints
        while (i <= -100) {
            q = i / 100;
            r = (q * 100) - i;
            i = q;
            putChar(buf, --charPos, Integer.DigitOnes[r]);
            putChar(buf, --charPos, Integer.DigitTens[r]);
        }

        // We know there are at most two digits left at this point.
        q = i / 10;
        r = (q * 10) - i;
        putChar(buf, --charPos, '0' + r);

        // Whatever left is the remaining digit.
        if (q < 0) {
            putChar(buf, --charPos, '0' - q);
        }

        if (negative) {
            putChar(buf, --charPos, '-');
        }
        return charPos;
    }
========================StringUTF16.class=============================
    @HotSpotIntrinsicCandidate
    // intrinsic performs no bounds checks
    static void putChar(byte[] val, int index, int c) {
        assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
        index <<= 1; // 和 index*2 等价,用来确定c在val中存储的起始位置,字节长度是数字字符串长度的两倍
        // val中两个字节存储c(00000000 xxxxxxxx)。
        // UTF-16中有字节序的概念,存储的时候,要区分子节序,即大小端
        // HI_BYTE_SHIFT和LO_BYTE_SHIFT其中一个是8,一个是0
        // 取c的高8位或低8位存储在val的低地址或高地址,达到大小端存储的目的。
        val[index++] = (byte)(c >> HI_BYTE_SHIFT);
        val[index]   = (byte)(c >> LO_BYTE_SHIFT);
    }
======================StringUTF16.class 大小端(字节序)==============================================
private static native boolean isBigEndian(); // 大端

    static final int HI_BYTE_SHIFT;
    static final int LO_BYTE_SHIFT;
    static {
        if (isBigEndian()) {
            HI_BYTE_SHIFT = 8;
            LO_BYTE_SHIFT = 0;
        } else {
            HI_BYTE_SHIFT = 0;
            LO_BYTE_SHIFT = 8;
        }
    }
==============Integer.class===============================
// 获取两位数10*a+b其十位(a)、个位(b)对应的字符'a'、'b'。
// 如下获取十位所对应的字符:
// byte i = (byte)10*a+b; // a,b属于10以内的数
// DigitTens[i] == a;// true
static final byte[] 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',
    } ;

static final byte[] 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',
    } ;

 2、public static String toString(int i,int radix)

返回用第二个参数指定基数表示的第一个参数的字符串表示形式。

源码:

==========================Integer.class=========================================
public static final int MIN_RADIX = 2;
public static final int MAX_RADIX = 36;
public static String toString(int i, int radix) {
    // 只支持2-36进制,范围之外的指定为10进制
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        radix = 10;

    /* Use the faster version */
    // 十进制则直接调用public static String toString(int i)方法
    if (radix == 10) {
        return toString(i);
    }
    // 单字节Latin1编码
    if (COMPACT_STRINGS) {
        // 将int型数据转为其他进制(2-36),只有2进制的结果其长度才最大
        // Integer.MIN_VALUE == -2147483648,2进制为-10000000000000000000000000000000,2进制长度为33
        // Integer.MAX_VALUE == 2147483647,2进制为1111111111111111111111111111111,2进制长度为31
        // 所以33个长度的buf数组足够。
        byte[] buf = new byte[33];
        // 是否为负数
        boolean negative = (i < 0);
        int charPos = 32;

        // 正数转为负数
        if (!negative) {
            i = -i;
        }

        // 十进制i转为其他进制
        while (i <= -radix) {
            buf[charPos--] = (byte)digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = (byte)digits[-i];

        // 负数则再加上负号
        if (negative) {
            buf[--charPos] = '-';
        }

        return StringLatin1.newString(buf, charPos, (33 - charPos));
    }
    // UTF-16编码
    return toStringUTF16(i, radix);
}
====================================Integer.class============================================
// 2-36进制所用到的字符
static final 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'
};
==================================StringLatin1.class==========================================
// Latin1编码
public static String newString(byte[] val, int index, int len) {
    return new String(Arrays.copyOfRange(val, index, index + len),
                      LATIN1);
}
String(byte[] value, byte coder) {
    this.value = value;
    this.coder = coder;
}
====================================Arrays.class==============================================
// 复制一份
public static byte[] copyOfRange(byte[] original, int from, int to) {
    int newLength = to - from;
    if (newLength < 0)
        throw new IllegalArgumentException(from + " > " + to);
    byte[] copy = new byte[newLength];
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}
==================================Integer.class===========================================
// UTF-16编码
private static String toStringUTF16(int i, int radix) {
    // 两倍字节存储
    byte[] buf = new byte[33 * 2];
    boolean negative = (i < 0);
    int charPos = 32;
    if (!negative) {
        i = -i;
    }
    // StringUTF16.putChar方法和前面一样。
    while (i <= -radix) {
        StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
        i = i / radix;
    }
    StringUTF16.putChar(buf, charPos, digits[-i]);

    if (negative) {
        StringUTF16.putChar(buf, --charPos, '-');
    }
    return StringUTF16.newString(buf, charPos, (33 - charPos));
}
=============================StringUTF16.class==========================================
public static String newString(byte[] val, int index, int len) {
    // 上面已经判断过COMPACT_STRINGS,所以此处不会进入if分支
    if (String.COMPACT_STRINGS) {
        byte[] buf = compress(val, index, len);
        if (buf != null) {
            return new String(buf, LATIN1);
        }
    }
    int last = index + len;
    // 单个字符占两字节,所以last乘2(last<<1)
    return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
}

 3、public static int bitCount(int i) 返回指定 int 值的二进制补码表示形式的 1 位的数量。

源码:

 1 @HotSpotIntrinsicCandidate
 2     public static int bitCount(int i) {
 3         // HD, Figure 5-2
 4         i = i - ((i >>> 1) & 0x55555555);
 5         i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
 6         i = (i + (i >>> 4)) & 0x0f0f0f0f;
 7         i = i + (i >>> 8);
 8         i = i + (i >>> 16);
 9         return i & 0x3f;
10     }

使用:

4、public static int parseInt(String s,int radix) throws NumberFormatException

使用第二个参数指定的基数,将字符串参数解析为有符号的整数。除了第一个字符可以是用来表示负值的 ASCII 减号 '-' ( 'u002D’)外,字符串中的字符必须都是指定基数的数字(通过 Character.digit(char, int) 是否返回一个负值确定)。返回得到的整数值。

源码:
public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
        /*
         * WARNING: This method may be invoked early during VM initialization
         * before IntegerCache is initialized. Care must be taken to not use
         * the valueOf method.
         */
        // 字符串s不能为null
        if (s == null) {
            throw new NumberFormatException("null");
        }

        // 进制不能小于2
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }

        // 进制不能大于36
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }

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

        if (len > 0) {
            char firstChar = s.charAt(0);
            // 若首字符ASCII值小于字符'0', 则可能是正负号
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') { // 负号
                    negative = true;
                    limit = Integer.MIN_VALUE; // 负数最小值
                } else if (firstChar != '+') { // 不是负号又不是正号,则非法,报错
                    throw NumberFormatException.forInputString(s);
                }
                // 字符串不能只有正负号
                if (len == 1) { // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                }
                i++; // 下标移动到第二个字符
            }
            int multmin = limit / radix; // ??????????????
            int result = 0;
            // 计算该radix进制字符串对应的10进制
            // 二进制11010计算十进制:
            // 第一种:1*2^4 + 1*2^3 + 0*2^2 + 1*2^1 + 0*2^0
            // 第二种:((((1*2+1)+0)*2+1)*2+0)*2
            // 下面计算10进制用的是第二种。
            while (i < len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                // 字符对应的十进制数,'0'=>0, '1'=>1, 'a'=>10, 'A'=>10
                int digit = Character.digit(s.charAt(i++), radix);
                if (digit < 0 || result < multmin) { // ??????????????
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) { // ??????????????
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
            return negative ? result : -result;
        } else {
            throw NumberFormatException.forInputString(s);
        }
    }
5、public static Integer decode(String nm)throws NumberFormatException 将 String 解码为 Integer。接受通过以下语法给出的十进制、十六进制和八进制数字
源码:
// 8进制:0开头
// 16进制:0x、0x、#开头
// 10进制:104
// 负数首位加负号(-)
public static Integer decode(String nm) throws NumberFormatException {
    // 默认10进制
    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);
    // Handle sign, if present
    if (firstChar == '-') { // 首位是负号
        negative = true;
        index++;
    } else if (firstChar == '+') // 首位是正数负号
        index++;

    // Handle radix specifier, if present
    // 以 0x 或 0X开头则是16进制
    if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
        index += 2;
        radix = 16;
    }
    // 以"#"开头的也是16进制
    else if (nm.startsWith("#", index)) {
        index ++;
        radix = 16;
    }
    // 不是16进制,而且以0开头,且0之后还有字符,则是8进制
    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 {
        // 最终实现在Integer.parseInt方法
        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;
}
原文地址:https://www.cnblogs.com/natian-ws/p/10242841.html