概要
今天突发好奇,想不明白string是如何转换为int的,于是翻开jdk的源码,收货挺大的。
parseInt(String s)
首先我们看parseInt这个方法,看下图,它又调用了parseInt(String s, int radix),这个方法才是String转换成int的主要过程。这个方法比较有趣,我们来一一分析它的实现机制。
public static int parseInt(String s) throws NumberFormatException {
//此处表示s默认为10进制
return parseInt(s,10);
}
//radix为s的进制格式,不能大于36也不能小于2,即最小为2进制,最大为36进制,36进制的得来是10个数字加26个字母
//例如,parseInt("Kona", 27) returns 411787
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
//拿到第i个数字并且格式化成10进制
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);
}
//使用负号进行计算 , -20-3=-23
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
Integer decode(String nm)
转换8进制,16进制,10进制到10进制
public static Integer decode(String nm) throws NumberFormatException {
int radix = 10;
int index = 0;
boolean negative = false;
Integer result;
if (nm.length() == 0)
throw new NumberFormatException("Zero length string");
char firstChar = nm.charAt(0);
// Handle sign, if present
if (firstChar == '-') {
negative = true;
index++;
} else if (firstChar == '+')
index++;
// Handle radix specifier, if present
if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (nm.startsWith("#", index)) {
index ++;
radix = 16;
}
else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
index ++;
radix = 8;
}
if (nm.startsWith("-", index) || nm.startsWith("+", index))
throw new NumberFormatException("Sign character in wrong position");
try {
result = Integer.valueOf(nm.substring(index), radix);
result = negative ? Integer.valueOf(-result.intValue()) : result;
} catch (NumberFormatException e) {
// If number is Integer.MIN_VALUE, we'll end up here. The next line
// handles this case, and causes any genuine format error to be
// rethrown.
String constant = negative ? ("-" + nm.substring(index))
: nm.substring(index);
result = Integer.valueOf(constant, radix);
}
return result;
}
String toString(int i, int radix)
public static String toString(int i, int radix) {
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
/* Use the faster version */
if (radix == 10) {
return toString(i);
}
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
//如果非负数,转成负数
if (
i = -i;
}
/** 12|2 ...0
* 6|2 ...0
* 3|2 ...1
* 1|2 ...1
* 类似这种除法...
**/
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (33 - charPos));
}
Integer valueOf(String s)
valueOf有点特殊,他缓存了-128到127的值,所以数字在此范围内都是取的同一个对象。
与其类似的还有
- Boolean:(全部缓存)
- Byte:(全部缓存)
- Character(<= 127缓存)
- Short(-128 — 127缓存)
- Integer(-128 — 127缓存)
- Long(-128 — 127缓存)
- Float(没有缓存)
- Doulbe(没有缓存)
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}