桥下红药

以无心之心读书

String是如何被转成Int的

总分类 0 评

以前没有想过这种问题,越是简单的API越是容易忽略这种小细节。抱着好奇心去看了看实现。

举个栗子:Integer.valueOf(“1”); valueOf 这个是如何实现的呢?主要是调用了 Integer.parseInt


public static int parseInt(String s, int radix) throws NumberFormatException { ....... int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; ...... 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; }

代码总结来说就是先截取字符串的第一位判断正负数,因为可能是”-1″或者”+1″。接着就去遍历字符串每个字符去调用了 Character.digit 方法。


public static int digit(int codePoint, int radix) { .... if (codePoint < 128) { // Optimized for ASCII int result = -1; if ('0' <= codePoint && codePoint <= '9') { result = codePoint - '0'; } else if ('a' <= codePoint && codePoint <= 'z') { result = 10 + (codePoint - 'a'); } else if ('A' <= codePoint && codePoint <= 'Z') { result = 10 + (codePoint - 'A'); } return result < radix ? result : -1; } // native 方法不用管 return digitImpl(codePoint, radix); }

这个方法更不难理解了,把 char 转成了int 也就是ascii编码,第一个判断小于128就是因为ascii编码数值最大127,如果不是ascill编码就进 digitImpl方法了。是 ascill 编码就开始判断是否是’0’~’9’、’a’~’z’、’A’~’Z’,这也能看出digit除了可以传数字外还可以传字母,第二个参数就是筛选的区间,比如0-9,radix就是10,valueOf方法里面调用的时候就给死了。

if ('0' <= codePoint && codePoint <= '9') {
    result = codePoint - '0';
}

显而易见了,result结果就是减出来的数字,然后把每个int拼接完整就是 Integer.parseInt 里while的那段代码。

最后回到Integer.valueOf


public static Integer valueOf(String s) throws NumberFormatException { return Integer.valueOf(parseInt(s, 10)); }

显而易见 结果是 parseInt 回返的,Integer.valueOf只是调用了自己的重载方法,就是去里面找结果的缓存,没有的话就new Integer(); 自此转换完成!

     /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

ps:按理来说核心操作ascii原理应该通用其他语言。

上一篇

发表评论