Java内置进制转换源码解析
在实际应用中我们经常要用到进制转换,Java的Integer类也已经为我们提供了响应的方法,如下面几个方法分别是将十进制转换为十六进制、八进制以及二进制。
//十进制转十六进制
public static String toHexString(int i) {
return toUnsignedString0(i, 4);
}
//十进制转八进制
public static String toOctalString(int i) {
return toUnsignedString0(i, 3);
}
//十进制转二进制
public static String toOctalString(int i) {
return toUnsignedString0(i, 1);
}
从上面的三个方法我们不难看出都是调用同一个方法,只是其中的shift参数不同。shift的取值为(log2 N)N为多少进制,即十六进制对应4,八进制对应3,二进制对应1.
下面的方法就是被调用的函数,其中比较关键的是字符数组空间的开辟以及将数字保存到字符数组中。
/**
* Convert the integer to an unsigned number.
* 将整形转换为无字符型
*/
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
//Integer.SIZE :int的长度==32
//Integer.numberOfLeadingZeros(val):计算一个整数二进制串左起连续0的个数
//如 5 = 101 ,即 返回值==32-3=29
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
//计算需要开辟的数组的内存空间,最小为1个字符
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);
}
/**
* Format a long (treated as unsigned) into a character buffer.
* @param val the unsigned int to format 整数值
* @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) 对应需要转换的进制,4->十六进制,3->八进制,1->二进制
* @param buf the character buffer to write to 数组
* @param offset the offset in the destination buffer to start at 数组起始位置偏移量
* @param len the number of characters to write 数组长度
* @return the lowest character location used
*/
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = 1 << shift;
int mask = radix - 1; //用来在下面控制选取的位数。如八进制对应111
do {
// 源整数与mask按位与,控制位数,如八进制得到的结果范围[0,7]
buf[offset + --charPos] = Integer.digits[val & mask];
// 相当于 val/(2^shift)
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}
/**
* All possible chars for representing a number as a String
* 在一个字符串中表示一个数字所有可能出现的字符
*/
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};