你真的了解Integer.parseInt()方法吗???

public static int parseInt(String s, int radix) throws Exception
    {
        /** 对字符串判空,注意这里并不是没有判断空内容(长度为0的空串),下面判断了 */
        if (s == null)
        {
            throw new RuntimeException();
        }

        /** Character.MIN_RADIX这个是java字符支持的最小进制编码 */
        /** Character.MIN_RADIX = 2  */
        if (radix < Character.MIN_RADIX)
        {
            throw new RuntimeException();
        }

        /** Character.MAX_RADIX这个是java字符支持的最大进制编码 */
        /** Character.MIN_RADIX = 36  */
        /** 涨知识了,java支持的最大字符编码进制是36 */
        if (radix > Character.MAX_RADIX)
        {
            throw new RuntimeException();
        }


        /** 一堆局部变量,用到的时候解释具体含义  */
        int result = 0;
        boolean negative = false;
        int i = 0, len = s.length();
        /** 这里注意和这个limit变量的初始化值,下文需要去对比*/
        int limit = -Integer.MAX_VALUE;
        int multmin;
        int digit;


        /** 这里是对字符串长度的判断,回顾方法开始时的提示*/
        if (len > 0)
        {
            /** 得到首位字符 */
            /** 小细节,本方法中去对比字符串中的字符的时候全部采用的charAt方法  */
            /** 并没有将字符串转换成char数组,哈哈,省去了一个数组长度的空间消耗 */
            /** 但是,同时需要每次去调用一次charAt方法,(String内部是有对应的char数组的) */
            char firstChar = s.charAt(0);

            /** 判断是否是非法字符,注意这里默认首位"+-"号都不算非法字符 */
            if (firstChar < '0')
            {
                /** 首位是负号 */
                if (firstChar == '-')
                {
                    /** negative在这里被置为了true,本身又是boolean值 */
                    /** 所以,很明显,negative是一个标识位 */
                    /** 标识的内容就是,当前字符串首位是否是负号 */
                    negative = true;

                    /** limit变量在首位是负号的时候,被置为了int类型范围内的最小值 */
                    limit = Integer.MIN_VALUE;
                }
                else if (firstChar != '+')
                {
                    /** ASCII码小于字符‘0’的情况下,不是负号,又不是正号,那就是非法字符 */
                    /** java中字符是有数值的,其数值对应ASCII中的值 */
                    throw new RuntimeException();
                }

                /** 如果上述没有抛出异常,证明首位一定是符号字符  */
                /** 首位符号字符的情况下,长度自然不能为1,显然一个数值不能只有一个符号 */
                if (len == 1)
                {
                    throw new RuntimeException();
                }

                /** 当正确执行到这里的时候,表明首位是符号位且符号位后续还有字符,i++ */
                /** i就是对当前字符串的字符位置的索引值,此时的i表明之后的操作从第二个字符开始 */
                /** 因为第一个字符已经处理完了(符号位) */
                i++;
            }

            /** radix是一个int值,数值内容代表当前数值是什么进制的编码 */
            /** radix=10,表明使用的编码进制是我们最常用的十进制编码 */
            /** 这条语句的含义就是把limit右移一位(无论是多少进制的编码) */
            /** 例如,十进制编码下limit = 123456;那limit/radix = 12345 */
            /** 记录一个这样的值,有什么意义,下文会理解 */
            multmin = limit / radix;

            /** 索引从左至右以此遍历字符串中的每一个字符 */
            while (i < len)
            {
                /** Character.digit(char a,int b):该方法是把a字符转换成对应b进制的数值 */
                /** 例如:Character.digit('1',10):结果就是数值1(十进制) */
                /** 注意此时的radix是10进制(我们以十进制调用该方法为例) */
                digit = Character.digit(s.charAt(i++),radix);

                /** 字符小于0,结束,证明其是非法字符 */
                if (digit < 0)
                {
                    throw new RuntimeException();
                }

                /** 这条语句先不看,等分析下面的语句后,才能明白这里的作用
                 *
                 *  这条语句在字符串的长度超过int值最大可接受长度的时候会拦截
                 *
                 *  比如字符串 21474836470 比Integer.MAX_VALUE的最大值还多出一位
                 *
                 *  这条语句就是解决了上述这个字符串的拦截
                 *  当已经执行到int所能承受的最大长度位数的时候,result - digit = -2147483647
                 *  这个值已经小于 multmin(multmin就是把limit右移一位)
                 *  所以之后雨果超过了这个长度,也就标识长度超过范围了已经
                 *  很有意思的一个设计点
                 *
                 **/
                if (result < multmin)
                {
                    throw new RuntimeException();
                }

                /** 这里是当前result左移一位,最后一位补0 */
                result *= radix;

                /** result < limit + digit 这样写不好直接理解 */
                /** 我们转换成 result - dight < limit
                 *  注意这次变换在编码是错误的,也就是代码必须写成第一种形式
                 *  因为第二种形式的 result - dight 是可能会越界的
                 *  第二种形式的转换只是为了帮助理解
                 *
                 *  一步一步分析啊:
                 *  ① 首先,limit在当前字符首位负号的时候是Integer.MIN_VALUE,
                 *    正号的时候是 -Integer.MAX_VALUE
                 *  ②  result是字符串从非符号位开始到当前索引的截取值
                 *  ③  这一条语句只有在被验证字符串恰好是int范围边界的时候才有用
                 *
                 *  举例子说明:Integer.MAX_VALUE = 2147483647 (一共10位)
                 *  假如我们的字符串是:s = "2147483648",一共10位
                 *  当前 i=10
                 *  那么此时的 result = -2147483640;digit = 8;
                 *  那么 result - digit = -2147483648 < limit
                 *
                 *  limit 在字符串是正数的时候是,- Integer.MAX_VALUE = -2147483647;
                 *  这就表示字符串越界了(超过范围了,如果是负数,逻辑一致)
                 *
                 * */
                if (result < limit + digit)
                {
                    throw new RuntimeException();
                }

                /** 这条语句其实是配合上面的 result *= radix 这条语句一起发挥作用的 */
                /** 其目的就是获得字符串中 前i个字符所形成的数值(符号位除外) */
                result -= digit;
            }
        }
        else
        {
            throw new RuntimeException();
        }

        /** negative就是字符串首位是否是负号的标识,这里就用上了 */
        /** 因为整个代码逻辑全部是以转换负数,按照字符串从左到右遍历字符,然后迭代循环递减并与最大承受范围对比的一个过程 */
        /** 其实也完全可以全部在正数逻辑上处理,之所以选择以负数处理,其实就是因为最小负数的绝对值比正数大1 */
        /** 也就是Integer.MIN_VALUE取不到相反数,已经越界了,哈哈  */
        return negative ? result : -result;
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值