面试官要求:表述清楚,让我和看到代码一样
一开始听到题目以为挺简单的,后面说了自己的方案,然后面试官说少了很多异常处理,后面面试结束亲自看了一下源码,发现底层实现(String.valueOf())加了很多异常处理。
1.函数传入参数需要转化的String str,以及字符串数字的进制数int radix
2.判断字符串是否为空
3.判断进制数是否超出进制数的最小范围(Java中Character.MIN_RADIX值为2,也就是二进制)
4.判断进制数是否超出进制数的最大范围(Java中Character.MAX_RADIX值为36,也就是三十六进制)
5.设置参数result(保存当前已转化位的结果),negative(是否为负数),i(当前在String中的索引位置,这里挺疑惑为什么不用index代替i,字义更加清晰),len(字符串的长度),limit(值为-Integer.MAX_VALUE,也就是最小值,后面还有个判断如果该数是负数,limit的值就为Integer.MIN_VALUE),multmin(用来提前判断然后避免result*radix溢出),digit(用来表示当前索引的字符经过进制转化之后的数字)
6.判断长度是否为零,为零的话退出
7.获取字符串首个字符并判断是否为是数字范围,不是的话判断是否是'-',是'-'的话将negative设为true,limit设为Integer.MIN_VALUE;如果不是'-'的话,再判断是否是'+',如果不是的话,抛出异常,是'+"的话,再判断长度是否为1,是的话抛出异常。不是的话i自加。
8.对字符串除首位外的字符进行遍历处理
9.每个索引的字符转成相应进制的数字(调用Character.digit())
10.如果转化后的数字小于0抛出异常
11.如果当前result(也就是已经转化好的部分)小于multmin,抛出异常
12.对result自乘radix,也就是将数字向左移位
13.然后判断result - digit的值是否会超出limit的范围,如果超出就抛出异常,没有超出就将result自减digit(默认全部当做负数处理,最后根据negative的值改变负号即可)
14.return negative? result:-result;
底层代码如下
/**
* Parses the string argument as a signed integer in the radix
* specified by the second argument. The characters in the string
* must all be digits of the specified radix (as determined by
* whether {@link java.lang.Character#digit(char, int)} returns a
* nonnegative value), except that the first character may be an
* ASCII minus sign {@code '-'} ({@code '\u005Cu002D'}) to
* indicate a negative value or an ASCII plus sign {@code '+'}
* ({@code '\u005Cu002B'}) to indicate a positive value. The
* resulting integer value is returned.
*
* <p>An exception of type {@code NumberFormatException} is
* thrown if any of the following situations occurs:
* <ul>
* <li>The first argument is {@code null} or is a string of
* length zero.
*
* <li>The radix is either smaller than
* {@link java.lang.Character#MIN_RADIX} or
* larger than {@link java.lang.Character#MAX_RADIX}.
*
* <li>Any character of the string is not a digit of the specified
* radix, except that the first character may be a minus sign
* {@code '-'} ({@code '\u005Cu002D'}) or plus sign
* {@code '+'} ({@code '\u005Cu002B'}) provided that the
* string is longer than length 1.
*
* <li>The value represented by the string is not a value of type
* {@code int}.
* </ul>
*
* <p>Examples:
* <blockquote><pre>
* parseInt("0", 10) returns 0
* parseInt("473", 10) returns 473
* parseInt("+42", 10) returns 42
* parseInt("-0", 10) returns 0
* parseInt("-FF", 16) returns -255
* parseInt("1100110", 2) returns 102
* parseInt("2147483647", 10) returns 2147483647
* parseInt("-2147483648", 10) returns -2147483648
* parseInt("2147483648", 10) throws a NumberFormatException
* parseInt("99", 8) throws a NumberFormatException
* parseInt("Kona", 10) throws a NumberFormatException
* parseInt("Kona", 27) returns 411787
* </pre></blockquote>
*
* @param s the {@code String} containing the integer
* representation to be parsed
* @param radix the radix to be used while parsing {@code s}.
* @return the integer represented by the string argument in the
* specified radix.
* @exception NumberFormatException if the {@code String}
* does not contain a parsable {@code int}.
*/
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");
}
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;
}