Integer.valueOf(String s)源码解读

刷leetcode正好刷到了字符串转int的题目,就看了看java源码是如何实现的,借鉴一下思路。

核心是parseInt(),至于Integer.valueOf()只是做了一个[-128,127]的常量池。


Integer.valueOf()

全部代码粘贴如下,去除了s空串与radix非法范围的异常校验。

public static int parseInt(String s, int radix)
            throws NumberFormatException
{
    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;
}

整体思路也好理解,字符串从左到右扫描,result从0开始,每读取1位新字符,等于进位一次,所以乘以进制。再减去digit。
举例说明读取“123”,result变化是0,-1,-12,-123。

这里主要聊聊result为什么采用减法而不是加法计算,以及边界值判定。

1.result采用减法而不是加法计算,就是为了让result变成一个负数。因为int是有符号数字,范围是[-2^31~2^31-1]。负数比正数多一位。如果result用正数存储,那么就不能存储2^31。也就没办法表示-2^31。

2.边界值判定
边界值判定依靠两个值,一个是limit,另一个是multmin。首先是limit选取,正数范围应该是2^31-1。因为计算过程变成负数,所以这里取-(2^31-1)。负数是-2^31,不用变。这里还有个注意点是比较顺序,result < limit + digit 的判断应该放在result -= digit;之前,否则运算完就直接溢出,判断不出来了。然后是multmin。为什么在limit之外还需要判断,因为result *= radix;也可能导致溢出。multmin是limit右移一位的值。这里直接举数字说明。int最多能存储-2147483648。如果出现-5555555555就不行。反向思维一下,最后一位没有读取前int能接收最大数字要在[-214748364,0]之间。至于-2147483649的合法性问题就是limit来判定的。同样,multmin的判断也要在result *= radix运算前面。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • The Integer class wraps a value of the primitive type int...
    0x70e8阅读 544评论 0 0
  • java.lang.Integer#parseInt() 源码分析 Integer#parseInt() 是我们经...
    mlya阅读 933评论 2 0
  • 最近在准备春招,刷到这样一道题“string 转换成 integer的方式及原理”,于是翻了翻源码,简单记录一下。...
    Xun_Moo阅读 378评论 0 0
  • 其他更多java基础文章:java基础学习(目录) 转载自 Java 源码学习系列(三)——Integer学习的过...
    Hiwayz阅读 729评论 0 0
  • Integer源码阅读: parseInt函数: 函数声明:public static int parseInt(...
    TailWU阅读 221评论 0 1