zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    JavaScript 高级
    JavaScript 归纳
    完全二叉树, 最大堆 , 堆排序
    二叉树
    Java秒杀系统方案优化 高性能高并发实战(1)
    精选 SQL 脚本
    树形结构有关的SQL
    在Sql server数据库中,关于触发器的创建、调用及删除
    SQLServer 唯一键约束和唯一索引有什么区别?
    很不错的 VBA 网址
  • 原文地址:https://www.cnblogs.com/natian-ws/p/10242841.html
Copyright © 2011-2022 走看看