Integer.toHexString(int num) 函數功能是將十進制數轉化為16進制,並返回16進制String字符串。
不過,它的原理是怎樣的呢? 我們今天來研究一下。
本文針對Java 8。
1. 查看下源碼的函數說明
Returns a string representation of the integer argument as an unsigned integer in base 16.
The unsigned integer value is the argument plus 2^32 if the argument is negative; otherwise, it is equal to the argument. This value is converted to a string of ASCII digits in hexadecimal (base 16) with no extra leading 0s.
The value of the argument can be recovered from the returned string s by calling Integer.parseUnsignedInt(s, 16).
If the unsigned magnitude is zero, it is represented by a single zero character '0' ('\u0030'); otherwise, the first character of the representation of the unsigned magnitude will not be the zero character. The following characters are used as hexadecimal digits:
0123456789abcdef
These are the characters '\u0030' through '\u0039' and '\u0061' through '\u0066'. If uppercase letters are desired, the String.toUpperCase() method may be called on the result:
Integer.toHexString(n).toUpperCase()
意思是說:
返回一個integer類型參數num所代表的無符號integer對應的16進制數的字符串。
如果num < 0,則無符號integer值+232(符號位由0變為1);如果num>=0,則無符號integer值 = num。 然后,這個無符號值轉換成一個以16進制形式的ASCII數字的字符串
參數值num能通過調用Integer.parseUnsignedInt(s, 16)從返回的string進行恢復。
如果無符號數值是0,那么它通過單個0字符 '0'('\u0030')來表示;否則,無符號數值16進制字符串首字母不會是0。后面的字符使用16進制數字:
0123456789abcdef
對應Unicode編碼0~9: '\u0030'~'\u0039'; a~f: '\u0061'~'\u0066'。
如果想用大寫字母,可以使用String.toUpperCase() 轉換結果:
Integer.toHexString(n).toUpperCase()
2. 查看Integer.java中toHexString原型
只有一個簡單調用
public static String toHexString(int i) {
return toUnsignedString0(i, 4);
}
繼續查看toUnsignedString0原型:
/**
* Convert the integer to an unsigned number.
*/
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val); // 得出val所占用二進制數的位數
int chars = Math.max(((mag + (shift - 1)) / shift), 1); // 要轉換成的String 緩沖區字符個數, 最少為1. 一般地,當mag == 4的倍數時,緩沖器個數=mag/4;當mag % 4不為0時,多余4的倍數部分也會占用一個額外的空間
char[] buf = new char[chars]; // 申請存儲shift對應進制的字符緩沖區
formatUnsignedInt(val, shift, buf, 0, chars); // 將val值,按shift對應進制,轉換成字符,存儲進buf緩沖區
// Use special constructor which takes over "buf".
return new String(buf, true); // 將char緩沖區結果轉換為String
}
繼續查看numberOfLeadingZeros和formatUnsignedInt
numberOfLeadingZeros 返回i對應二進制數,從左邊開始連續0的個數;
formatUnsignedInt
/**
* Returns the number of zero bits preceding the highest-order
* ("leftmost") one-bit in the two's complement binary representation
* of the specified {@code int} value. Returns 32 if the
* specified value has no one-bits in its two's complement representation,
* in other words if it is equal to zero.
*
* @param i the value whose number of leading zeros is to be computed
* @return the number of zero bits preceding the highest-order
* ("leftmost") one-bit in the two's complement binary representation
* of the specified {@code int} value, or 32 if the value
* is equal to zero.
*/
public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
int n = 1;
if (i >>> 16 == 0) { n += 16; i <<= 16; }
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
n -= i >>> 31;
return n;
}
/**
* 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)
* @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; // 將shift轉化成進制數值,shift=4 代表16進制(radix=16)
int mask = radix - 1; // radix進制下最大值,也是各位全1的mask
// 從緩沖區末尾向頭部填充數據
do {
buf[offset + --charPos] = Integer.digits[val & mask]; // 將val對應16進制字符,填充進buf數組。這里由於val與mask進行了& 位運算,結果不可能超過mask,也就是說如果16進制只會對應索引為0~15的digits數
val >>>= shift; // 將val無符號右移shift位
} while (val != 0 && charPos > 0); // 最終循環退出條件要么為val = 0,要么是charPos = 0。通常是2者同時到0
return charPos;
}
查看Integer.digits
/**
* 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'
};