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]进制转为十进制

高并发编程thirft源码解析

Integer.parseInt(String s) 和 Integer.valueOf(String s) 的区别

Integer.parseInt("") Integer.valueOf("")和new Integer("")之间的区别