首页 > 其他 > 详细

Integer.parseInt 源码解析

时间:2021-03-29 20:47:19      阅读:23      评论:0      收藏:0      [点我收藏+]

parseInt()方法的用法:

parseInt是Integer类中提供的一个静态方法

用于将传入的string类型字符串根据要求转为相应进制的int值, 如果没有要求进制则按10进制计算

//如果只传入一个参数,则将传入参数转为10进制数
public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
    }

 源码分析

    public static int parseInt(String s, int radix) throws NumberFormatException {
//        判断传入的值是否为null,如果为null则抛出数字格式异常
        if (s == null) {
            throw new NumberFormatException("null");
        }
//        判断传入进制是否小于2,如果小于2则抛出数字格式异常
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " less than Character.MIN_RADIX");
        }
//        判断传入进制是否大于于36,如果大于36则抛出数字格式异常
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " greater than Character.MAX_RADIX");
        }
//         result为最终传回结果
        int result = 0;
//         negative为判断返回值的正负
        boolean negative = false;
//         i 为循环变量  len为传入字符串长度
        int i = 0, len = s.length();
//         -2147483647 默认取最大整数的取反值
        int limit = -Integer.MAX_VALUE;
//          用于在添加下一位数字前判断是否有溢出
        int multmin;
//
        int digit;
//       字符串是否有符号
        if (len > 0) {
//            获取传入字符串的第一位
            char firstChar = s.charAt(0);
//            判断字符串的ASCII码值是否大于‘0‘的ASCII码值,
            if (firstChar < ‘0‘) { // Possible leading "+" or "-"
//                如果字符串第一位是‘-‘则将negative赋值为true
                if (firstChar == ‘-‘) {
                    negative = true;
                    limit = Integer.MIN_VALUE;
//                    判断传入字符串的第一位是否为‘+‘
                } else if (firstChar != ‘+‘)
//                    不为‘+‘, 抛出数字格式异常
                    throw NumberFormatException.forInputString(s);
//               首字符为‘+‘但是传入字符串长度为1,抛出数字格式异常
                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
//                当第一位有符号时, 循环遍历数组时从第二位开始遍历
                i++;
            }
//             multmin = -214748364 负数跟整数的limit是不同的
            multmin = limit / radix;
//            循环追加数字  
            while (i < len) {
//                获取字符转换为相应进制的整数
                digit = Character.digit(s.charAt(i++), radix);
//                传回数字小于0时,抛出数字格式异常
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
//                 因为是负值存储, 所以当result小于multmin时说明越界了,
//                 如果当前数值已经超过了 multmin, 那么说明在添加当前数值之前就已经越界了
//                 直接抛出异常. 提前判断一次的原因, 是因为防止下一步越界
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
//                在更新 result 值之前, 先比较 result 和 multmin
//                如果已经越界了, 那么再进行这一步操作就会越界
                result *= radix;
//                  判断加了当前值之后是否越界
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
//                使用负数存储, 通过上面的代码使得这一步不会发生溢出
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
//        根据negative的值判断返回值是否取反
        return negative ? result : -result;
    }

 异常检测

//        判断传入的值是否为null,如果为null则抛出数字格式异常
        if (s == null) {
            throw new NumberFormatException("null");
        }
//        判断传入进制是否小于2,如果小于2则抛出数字格式异常
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " less than Character.MIN_RADIX");
        }
//        判断传入进制是否大于于36,如果大于36则抛出数字格式异常
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " greater than Character.MAX_RADIX");
        }

 

进入方法会先进行异常检测, 判断输入的信息是否合法

如果传入信息为null或进制不在取值范围内则抛出异常

进制的有效范围时2-36

定义变量

//         result最终传回结果
        int result = 0;
//         negative判断返回值的正负
        boolean negative = false;
//         i循环变量  len传入字符串长度
        int i = 0, len = s.length();
//        Integer.MAX_VALUE=-2147483647 默认取最大整数的取反值
        int limit = -Integer.MAX_VALUE;
//          用于在添加下一位数字前判断是否有溢出
        int multmin;
//          解析每一位数字
        int digit;

 

根据result , negative , len , digit四个变量来获取返回数值的最后情况

int的取值范围时 -232~232 -1

由于正负数的取值范围不同当传入值为-2147483648时 , 需要存储一个2147483648的值 , 如果使用int直接存储会发生溢出

为避免溢出所以使用负值存储

正负号判断

//       字符串是否有符号
        if (len > 0) {
//            获取传入字符串的第一位
            char firstChar = s.charAt(0);
//            判断字符串的ASCII码值是否大于‘0‘的ASCII码值,
            if (firstChar < ‘0‘) { // Possible leading "+" or "-"
//                如果字符串第一位是‘-‘则将negative赋值为true
                if (firstChar == ‘-‘) {
                    negative = true;
                    limit = Integer.MIN_VALUE;
//                    判断传入字符串的第一位是否为‘+‘
                } else if (firstChar != ‘+‘)
//                    不为‘+‘, 抛出数字格式异常
                    throw NumberFormatException.forInputString(s);
//               首字符为‘+‘但是传入字符串长度为1,抛出数字格式异常
                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
//                当第一位有符号时, 循环遍历数组时从第二位开始遍历
                i++;
            }

 

数值分析

//            循环追加数字  
            while (i < len) {
//                获取字符转换为相应进制的整数
                digit = Character.digit(s.charAt(i++), radix);
//                传回数字小于0时,抛出数字格式异常
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
//                 因为是负值存储, 所以当result小于multmin时说明越界了,
//                 如果当前数值已经超过了 multmin, 那么说明在添加当前数值之前就已经越界了
//                 直接抛出异常. 提前判断一次的原因, 是因为防止下一步越界
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
//                在更新 result 值之前, 先比较 result 和 multmin
//                如果已经越界了, 那么再进行这一步操作就会越界
                result *= radix;
//                  判断加了当前值之后是否越界
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
//                使用负数存储, 通过上面的代码使得这一步不会发生溢出
                result -= digit;
            }

 

multmin的使用原因

在源码中multmin的取值时

multmin = limit / radix;

 

当传入值具有符号时出去最后一位的最大值是-214748364到214748364

当解析数为2147483650时超过了最大取值范围 , 去除最后一位后取值为214748365 , 如果执行result*=radix 则result=2147483650已经越界所以无需继续执行result -= digit , 此时就需要提前判断并提前抛出异常

result<limit+digit

可以理解为判断传入数值是否为-2147483649(-232-1)

这部分的执行逻辑是判断加上当前位数值之后是否会发生越界 , 

可以理解为result-digit<limit

可是如果使用result-digit当传入值为-2147483649(-232-1)时result-digit会发生越界

但是写成result<limit+digit就不会发生溢出

总结

解析数值需要注意的地方有很多 , 尤其要避免传入的数值是否会产生溢出 , 

 

Integer.parseInt 源码解析

原文:https://www.cnblogs.com/Leo-Heng/p/14590370.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!