java integer.tohexstring_Java源码解析:Integer.toHexString

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'

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值