0%

Integer-parstInt源码解读

parseInt(String s)

java的parseInt函数可以将传入的字符串转换成数字,如果传入的字符串不满足要求,例如转换后的值过大,符号位过多,或者包含字母,则会进行异常的抛出

默认的parseInt是会调用一个可以传入进制数的函数

1
2
3
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}

其中radix是进制,传入的radix为10就是说按照十进制的方式来计算传入的string的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public static int parseInt(String s, int radix)
throws NumberFormatException
{
/*
* WARNING: This method may be invoked early during VM initialization
* before IntegerCache is initialized. Care must be taken to not use
* the valueOf method.
*/

//如果传入null,或者传入的进制不满足要求,直接抛出异常
//支持的进制范围是 2~36

if (s == null) {
throw new NumberFormatException("null");
}

if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}

if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}

int result = 0;
boolean negative = false;
int i = 0, len = s.length(); //用来控制循环进度
int limit = -Integer.MAX_VALUE; //边界大小
int multmin;
int digit;
//判断第一位是否为符号位,如果不是符号位也不是数字,直接扔出异常,如果是符号位,修改最大范围

if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);

if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
//根据最大值,以及进制数,计算出
//如果为正数,limit为-Integer.MAX_VALUE
//如果为负数,limit为Integer.MIN_VALUE,也就是说limit一直为负值
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
//获取到数字的值,如果小于0则抛出异常,如果小于
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
//因为result一直为正值,如果小于multmin说明有异常
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
//进位
result *= radix;
//如果result<limit+digit 也就是result-digit < limit,说明越界了
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
//倒着计算值
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
//如果为符号为负,直接返回,否则取反,因为result是倒着计算的,取反之后为正数
return negative ? result : -result;
}

解读

  1. 首先判断首位是否为符号位,如果是符号位,则记录符号值,并更新limit值。

  2. limit始终为负值,如果符号位为负,则limit为Integer.MIN_VALUE,如果为正,则limit为Integer.MAX_VALUE的负值

  3. 计算的时候,会利用到multmin,主要是用来判断进位后的结果是否超过了limit。

    $mulmin = limit/radix$

    $mulmin*radix = limit$

    所以如果$result < mulmin$,也就等价于 $result * radix < limit$,也就是越界了,直接抛出异常

  4. 因为Integer.MAX_VALUE 和Integer.MIN_VALUE 不同,分开计算区间会比较麻烦,所以上面的做法是全部转为计算负值,进而是采用减法操作。因为抛开符号位来说,数值的计算方法是一样的,只是区间不同。比如是312,在进行计算的时候,会先计算出来-3,然后计算出来-31,再计算出来-312。然后取反,得到312

  5. 因为ASCII码中数字只有0-9,所以只需要判断char是否在当前范围即可。如果要处理的char是数字,则再进行下一步计算