面试 | String 转换成 Integer 的方式及原理?

大体思路:
示例,调用Integer类的parseInt()方法;

public static void method() {
	String str = "-255";
	Integer num = Integer.parseInt(str);
	System.out.println(num);
}
默认十进制,也可以手动传其他进制来规定要把str字符串转换成什么进制的数字;
public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
    }
下面代码主要思路具体看注释;总结下方法的主要思路:
  • 1 参数校验,包括字符串和进制;字符串不为null,进制在[2,36]之间.
  • 2 字符串长度不为0,即不为空;否则抛出异常;
  • 3 开始处理字符串
    • 3.1 取字符串第一位字符,根据字符的ASCII码与‘0’的ASCII码比较判断是否是’+'或者‘-’;
    • 3.2 确定正负数后,逐位获得每位字符的int值;(如何实现看下面的分析)
    • 3.3 通过*=和-=对各结果进行拼接;
  • 4 根据是否是负数返回相应的结果;
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.
         */

        if (s == null) {
            throw new NumberFormatException("null");
        }
        // 进制数最小为2,radix小于最小进制则抛异常
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
        // 进制数最大为36,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);
            // ‘-’ 和 ‘+’ 的ASCII码分别为45和43,都小于字符‘0’的ASCII码48
            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
                // 这个方法比较关键,主要作用是根据字符的ASCII码把字符转换成int类型,如字符‘2’,则返回int类型的2,具体分析看下面;
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                // 这边就是对返回int作一系列的拼接运算,得到个、百、千位的结果
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }

Character.digit(s.charAt(i++),radix);

调用Character类的digit方法。把字符ch换算成int类型,即对应的ASCII码值。
public static int digit(char ch, int radix) {
       return digit((int)ch, radix);
}
根据ASCII码值获得相应的CharacterData对象,对象中有判断字符属性的方法;

PS:CharacterDataLatin1,CharacterData00和CharacterData01等对象可以自行百度解释。推荐这篇博客的介绍:

public static int digit(int codePoint, int radix) {
      return CharacterData.of(codePoint).digit(codePoint, radix);
}

static final CharacterData of(int ch) {
        if (ch >>> 8 == 0) {     // fast-path
            return CharacterDataLatin1.instance;
        } else {
            switch(ch >>> 16) {  //plane 00-16
            case(0):
                return CharacterData00.instance;
            case(1):
                return CharacterData01.instance;
            case(2):
                return CharacterData02.instance;
            case(14):
                return CharacterData0E.instance;
            case(15):   // Private Use
            case(16):   // Private Use
                return CharacterDataPrivateUse.instance;
            default:
                return CharacterDataUndefined.instance;
            }
        }
    }
示例中返回的是CharacterDataLatin1对象,所以看一下该对象的digit()方法:
int digit(int ch, int radix) {
        int value = -1;
        if (radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX) {
            int val = getProperties(ch);   // 获取这个字符对应的属性值为A[ch]
            int kind = val & 0x1F;
            if (kind == Character.DECIMAL_DIGIT_NUMBER) {
                // 根据val的后5位获得该val代表的整型值,就是我们想要的结果
                value = ch + ((val & 0x3E0) >> 5) & 0x1F;
            }
            else if ((val & 0xC00) == 0x00000C00) {
                // Java supradecimal digit
                value = (ch + ((val & 0x3E0) >> 5) & 0x1F) + 10;
            }
        }
        return (value < radix) ? value : -1;
    }

这个方法的背景可以看上面提到的博客,不然理解不了。

你可能感兴趣的:(Java基础知识,Java基础面试题)