最近在准备春招,刷到这样一道题“string 转换成 integer的方式及原理”,于是翻了翻源码,简单记录一下。
valueOf方法定义如下,可以看到方法中直接调用了parseInt,并默认使用十进制转换
public static Integer valueOf(String s) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, 10));
    }
接下来详细看一下parseInt方法
public static int parseInt(String s, int radix) throws NumberFormatException
    {
        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++;
            }
            multmin = limit / radix;
            while (i < len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }
实现思路整理如下
- 判断字符串是否为null,若为null则直接抛出异常。 
- 判断进制是否超出范围(小于2或大于36) 
- 当字符串长度大于0时,先判断是否起于‘-’或者‘+’符号,并排除单符号情况 
- 
遍历字符串,利用Character.digit方法将char转换成int,并加到记录结果的result变量上。在这里进行了三次检查 - if (digit < 0):非法字符,无法转换成int 
- if (result < multmin):为‘result *= radix;’语句做准备,避免溢出。这里multmin = limit / radix; 
- if (result < limit + digit):为‘result -= digit;’语句做准备,避免溢出。注意这里不能写成‘result- digit < limit;’ 
 
- 最后判断正负并返回结果 
注意到一点,该方法在计算过程中所有数据均按照负数处理。个人觉得主要是简化了计算情况,同时只需要检查单边界。