Integer.parseInt不同jdk源码解析
Posted 星火燎原智勇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Integer.parseInt不同jdk源码解析相关的知识,希望对你有一定的参考价值。
执行以下代码:
System.out.println(Integer.parseInt("-123")); System.out.println(Integer.parseInt("+123"));
以上提供1.6、1.7和1.8三个版本的比较
1.6版本执行结果为:
1.7版本执行结果为:
1.8版本执行结果为:
从两方面去查证结果的原因,分别是:查看API文档 和 查看对应的源代码
【查看API文档】
1.6版本对应的API文档:
1.7版本对应的API文档:
1.8版本对应的API文档:
可以看出,对第一个首字符,1.6只对 \'-\' 做了判定;1.7和1.8对 \'-\' 和 \'+\' 都做了判定。
【查看JDK源码】
1.6版本对应的源代码:
1 char firstChar = s.charAt(0); 2 if (firstChar < \'0\') { // Possible leading "+" or "-" 3 if (firstChar == \'-\') { 4 negative = true; 5 limit = Integer.MIN_VALUE; 6 } 7 8 if (len == 1) // Cannot have lone "+" or "-" 9 throw NumberFormatException.forInputString(s); 10 i++; 11 }
1.7版本对应的源代码:
1 char firstChar = s.charAt(0); 2 if (firstChar < \'0\') { // Possible leading "+" or "-" 3 if (firstChar == \'-\') { 4 negative = true; 5 limit = Integer.MIN_VALUE; 6 } else if (firstChar != \'+\') 7 throw NumberFormatException.forInputString(s); 8 9 if (len == 1) // Cannot have lone "+" or "-" 10 throw NumberFormatException.forInputString(s); 11 i++; 12 }
1.8的和1.7的源代码一样,这里就不冗余贴出来了。
对应jdk1.8源代码并做了相应的注解源码如下所示,帮助大家一起更加深入的理解:
1 public static int parseInt(String s, int radix) throws NumberFormatException { 2 /* 3 * WARNING: This method may be invoked early during VM initialization 4 * before IntegerCache is initialized. Care must be taken to not use 5 * the valueOf method. 6 */ 7 // 下面三个判断好理解,其中表示进制的 radix 要在(2~36)范围内 8 if (s == null) { 9 throw new NumberFormatException("null"); 10 } 11 12 if (radix < Character.MIN_RADIX) { 13 throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); 14 } 15 16 if (radix > Character.MAX_RADIX) { 17 throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); 18 } 19 20 /** 21 * 表示结果, 在下面的计算中会一直是个负数 22 * 假如说 我们的字符串是一个正数 "7",那么在返回这个值之前result保存的是 -7 23 * 这个可能是为了保持正数和负数在下面计算的一致性 24 */ 25 int result = 0; 26 boolean negative = false; 27 int i = 0, len = s.length(); 28 29 /** 30 * limit 默认初始化为 最大正整数的 负数 ,假如字符串表示的是正数 31 * 那么result(在返回之前一直是负数形式)就必须和这个最大正数的负数来比较,判断是否溢出 32 */ 33 int limit = -Integer.MAX_VALUE; 34 int multmin; 35 int digit; 36 37 if (len > 0) { 38 char firstChar = s.charAt(0); //首先是对第一个位置判断,是否含有正负号 39 if (firstChar < \'0\') { // Possible leading "+" or "-" 40 if (firstChar == \'-\') { 41 negative = true; 42 //这里在负号的情况下,判断溢出的值就变成了 整数的 最小负数了 43 limit = Integer.MIN_VALUE; 44 } else if (firstChar != \'+\') 45 throw NumberFormatException.forInputString(s); 46 47 if (len == 1) // Cannot have lone "+" or "-" 48 throw NumberFormatException.forInputString(s); 49 i++; 50 } 51 multmin = limit / radix; 52 /** 53 * len为输入字符串的长度,i为循环len自增变量 54 * result初始值为0,multmin初始值为最大负整数/进制数 55 */ 56 while (i < len) { 57 // Accumulating negatively avoids surprises near MAX_VALUE 58 //根据Character类获取当前对应字符对应进制的数字 59 digit = Character.digit(s.charAt(i++),radix); 60 if (digit < 0) { 61 throw NumberFormatException.forInputString(s); 62 } 63 64 /** 65 * 这里就是上面说的判断溢出,由于result统一用负值来计算,所以用了 小于 号 66 */ 67 if (result < multmin) { 68 throw NumberFormatException.forInputString(s); 69 } 70 result *= radix; 71 if (result < limit + digit) { 72 throw NumberFormatException.forInputString(s); 73 } 74 result -= digit; 75 /** 76 * 再来个假设:一开始输入一个数字字符串为123,那么对应的radix=10(因为是10进制的),digit = 123 / 10 计算得到的 77 * 第一次result *= radix --> result = 0 ; result -= digit --> result = -1 78 * 第二次result *= radix --> result = -10; result -= digit --> result = -12 79 * 第三次result *= radix --> result = -12; result -= digit --> result = -123 80 * 此时,negative = false,则返回 -result,即最终结果为:123 81 */ 82 } 83 } else { 84 throw NumberFormatException.forInputString(s); 85 } 86 return negative ? result : -result; 87 }
从以上源码可以看出,作者在计算整型数字的时候是采用取反的操作,即正数是通过负数进行计算,返回再取反操作。我猜想这样是为了在计算正负数的时候采取相同的策略,不需要为正数写一套方案,负数写一套方案,可以避免重复代码的嫌疑。
以上是关于Integer.parseInt不同jdk源码解析的主要内容,如果未能解决你的问题,请参考以下文章
Integer.valueOf() 与 Integer.parseInt() [重复]
为啥 Double.parseDouble(null) 和 Integer.parseInt(null) 会抛出不同的异常?
JavaSE8基础 Integer.parseInt 将[2,36]进制转为十进制
Integer.parseInt(String s) 和 Integer.valueOf(String s) 的区别
Integer.parseInt("") Integer.valueOf("")和new Integer("")之间的区别