1:首先我们可以通过一个main函数,通过断点调试,正式开启Integer.toString()方法之旅。
public static void main ( String[] arg ) {
System.out.println( Integer.toString( 65537 ) );
}
2: 首先我们会看到进入toString(int i)的方法之内
public static String toString(int i) {
if (i == Integer.MIN_VALUE) (1)
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); (2)
char[] buf = new char[size]; (3)
getChars(i, size, buf); (4)
return new String(buf, true); (5)
}
从(1)中我们就可以看到 判断是否为整数的最小的数,是的话,直接返回"-2147483648"字符串,在(2)中这里通过 stringSize(-i) 判断是否为小数 二进制中,小数的第一位是符号位,负数等于所比正数多了一位,在(3)中新创建了一个char[]数组,我们通过研究string的源码可知,String的本质就是一个char[]数组,对String的操作,就是操作char[]里面的每一个对象,为了搞清楚(4)与(5)的作用,首先,我们先进入stringSize(i)的方法里面都看看做了什么。
3: 高效的位数计算方法 stringSize(i);
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
static int stringSize(int x) {
for (int i=0; ; i++) (1)
if (x <= sizeTable[i]) (2)
return i+1;
}
从(1)中可知,首先进入一个无限for循环中,但是由于sizeTable参数的限制,其实最多可以循环10此,例如我们,断点调试时传入的值是65537,那么它就会循环5次,得到是一个5位的数字,那么就返回4。char[] buf = new char[4],
正好就可以创建一个正好放下65537的数组。
4: 功能强大的getChars(i, size, buf);
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) { (1)
sign = '-';
i = -i;
}
while (i >= 65536) { (2)
q = i / 100;
r = i - ((q << 6) + (q << 5) + (q << 2)); (3)
i = q;
buf [--charPos] = DigitOnes[r]; (4)
buf [--charPos] = DigitTens[r]; (5)
}
for (;;) { (6)
q = (i * 52429) >>> (16+3); (7)
r = i - ((q << 3) + (q << 1)); (8)
buf [--charPos] = digits [r]; (9)
i = q;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign; (10)
}
}
从(1)处可知,我们知道负数的第一位是“-”号,并且负数比正数多了一位,除了“-”号位之外,所有的内容和正数完全相同,紧接着,会进入(2)的一个循环语句,为什么是65536呢,我们知道65536正好等于2的16次方,二正数的最大值是2的32次方减1,可以说,65536是正数的最大值的一半,大于65536的位高位数,小于65536的是低位数,65537/100正好是655,((q << 6) + (q << 5) + (q << 2))这一段的作用等于 (q * 100),通过位运算与加法运算,避免乘除运算以提高效率。紧接着r=37进入(4)和(5)的数组,(4)和(5)的数组设计简直称为神奇。
final static char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
final static char [] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
通过这两个数组,正好得到buf [4]=7,buf [3]=3的值。接下来,就会进入(6)为代表的for无限循环中(其实有限的,这样写感觉好精炼),(7)的作用相当于除以10,右移16+3也就是右移19位,也就是除以2的19次方,2的19次方=524288 ,而52429除以524288为0.1000003814697266的精度已经很多了,就几乎等于0.1,而52429/524288得到的数字精度在不超出整形范围内,精度是最高的。(8)r = i - ((q << 3) + (q << 1))相当于r = i-(q*10),也是为了提高运算效率。类似的通过(9)与(10)即可得到字符数组 char[] ={"6","5","5","3","7"}
至此,最后调用new String(buf, true)方法,返回想要的字符串
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。