原文在这里,感谢作者,这里我做一些记录和补充。
Integer.toHexString(int)是将一个整型转成一个十六进制数。类似功能的方法还有toOctalString(int)、toBinaryString(int)。
它们的内部实现如下:
public static String toHexString(int i) {
return toUnsignedString0(i, 4);
}
public static String toOctalString(int i) {
return toUnsignedString0(i, 3);
}
public static String toBinaryString(int i) {
return toUnsignedString0(i, 1);
}
toUnsignedString0(int,int)代码如下:
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
//计算这个int转换成二进制后占多少bit(123-->>7)
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
//用于确定最后生成的字符串有几个字符
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
char[] buf = new char[chars];
//具体解析出每个字符是什么
formatUnsignedInt(val, shift, buf, 0, chars);
// Use special constructor which takes over "buf".
return new String(buf, true);
}
分析一个例子:
Integer.numberOfLeadingZeros(123);
1、首先会执行第一句int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
那么Integer.numberOfLeadingZeros(val)会返回什么呢?
看Debug图:
numberOfLeadingZeros(123)返回的是25。为什么是25呢?
因为123的二进制是 0000 0000 0000 0000 0000 0000 0111 1011。数一数前面有多少个0?
所以numberOfLeadingZeros(val)的作用是 返回二进制串中从最左边算起连续的“0”的总数量。
原文没有分析这个算法,这里我着重分析一下,看看这个算法的趣味!看下图:
这个是一个二分算法,将二进制串拆成二部分,先分析前16位是否都为0,是则将后16位挪为前16位继续分析,否则只需分析前16位即可。这中间使用右移来判断是否为0,左移改变分析对象进行下一步分析,很巧妙。类似的,numberOfTrailingZeros(int i) 这个方法则是给定一个int类型数据,返回这个数据的二进制串中从最右边算起连续的“0”的总数量。
2、所以 int mag = 32-25=7。
第二行int chars = Math.max(((mag + (shift - 1)) / shift), 1);等于
int chars = Math.max((7+3)/4,1)=2
3、继续看formatUnsignedInt()内部:
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = 1 << shift;//2^shift (此例子是2^4)
int mask = radix - 1; //(16进制-->>15 8进制-->>7)
do {
//val&mask 相当于 val%(mask+1) 这里是 123%16
buf[offset + --charPos] = Integer.digits[val & mask];
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}
进入此函数后,mask=15
第一次do…while
buf[1] = Integer.digits[123&15] //’b’ 98
123>>>4 //此时val =7
….省略第二次
最后的 char[] buf = [‘7’,’b’]
所以最后toHexString 的结果就是 123—>>> 7b