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 = limit / radix;
当传入值具有符号时出去最后一位的最大值是-214748364到214748364
当解析数为2147483650时超过了最大取值范围 , 去除最后一位后取值为214748365 , 如果执行result*=radix 则result=2147483650已经越界所以无需继续执行result -= digit , 此时就需要提前判断并提前抛出异常
可以理解为判断传入数值是否为-2147483649(-232-1)
这部分的执行逻辑是判断加上当前位数值之后是否会发生越界 ,
可以理解为result-digit<limit
可是如果使用result-digit当传入值为-2147483649(-232-1)时result-digit会发生越界
但是写成result<limit+digit就不会发生溢出
解析数值需要注意的地方有很多 , 尤其要避免传入的数值是否会产生溢出 ,
原文:https://www.cnblogs.com/Leo-Heng/p/14590370.html