今天看到一道笔试题:String类中,使用哪个方法可以将int值100转换成字符串?写出具体方法:
挺简单的,学过Java基础应该都知道,String.valueOf(100)就能完成。今天就想着看看里面是啥。
参考(建议直接看链接3):
- Integer源码分析 - zxcvbnmzsedr - 简书
- java源码中Integer.class中有个getChars方法,里面有个52429是怎么确定的? - 知乎
- Java 源码学习系列(三)——Integer 写的真心不错,网站已收藏。
写了个代码测试一下:
public class Test {
public static void main(String[] args) {
System.out.println(String.valueOf(100));
}
}
进入String.valueOf(int i)方法:
public static String valueOf(int i) {
return Integer.toString(i);
}
String有点懒,啥都不干,直接调用Integer.toString(int i)方法。所以重点是Integer.toString(int i)方法,跟String.valueOf(int i)方法半毛钱关系没有。
进入Integer.toString(int i)方法:
public static String toString(int i) {
// 如果i是-2147483648,stringSize(-i)取反的时候会溢出,正数最大为2147483647,所以单独判断
if (i == Integer.MIN_VALUE)
return "-2147483648";
// 获取i的长度。如果i是负数,负号也算一位,所以要加1
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
// 创建相应长度的字符数组,存储i
char[] buf = new char[size];
// 将i转换为字符数组,存储在buf中
getChars(i, size, buf);
// 调用String类的package构造方法,转为字符串,Integer和String都是java.lang包下的类
return new String(buf, true);
}
里面有:stringSize(int x),getChars(int i, int index, char[] buf)和String(char[] value, boolean share)三个方法。
Integer类的stringSize(int x)方法如下:
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// package静态方法
// JDK规定x必须是非负数,取值范围是[0, 2147483647]
static int stringSize(int x) {
// 获取x的长度
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
上面的方法没什么好说的,下面看看getChars方法(😂源码中上面这段代码和下面这段代码是邻居):
// 将i转成字符数组存储在buf中
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;// 符号
// 如果是负数,保存负号,并取反
if (i < 0) {
sign = '-';
i = -i;
}
// 每次迭代生成两位数,减少循环的次数
while (i >= 65536) {
q = i / 100;// 商
// 等价于:r = i - (q * 100);
// 100 = 2^6 + 2^5 + 2^2
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;// 更新i
buf [--charPos] = DigitOnes[r];// 将个位赋值给数组
buf [--charPos] = DigitTens[r];// 将十位赋值给数组
}
// 下降到快速模式为较小的数字,每次迭代生成一位数
for (;;) {
// 参考上面的while循环可知,这里应该是q = i / 10,具体分析见http://www.hollischuang.com/archives/1058
q = (i * 52429) >>> (16+3);
// 等价于:r = i-(q*10)
// 10 = 2^3 + 2^1
r = i - ((q << 3) + (q << 1));
// 通过映射表(digits数组),将i对应的字符赋给buf数组
buf [--charPos] = digits [r];
i = q;// 更新i
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;// 负号
}
}
分析我不想写了。
关键点:
移位操作比乘法操作快
乘法操作比除法操作快
精确度,溢出等因素
String构造方法
// String类的package构造方法,直接赋值比使用public的String构造方法(复制数组)快。
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}