Java Object 通用方法 toString() 之 Integer.toHexString(),
分享于 点击 9487 次 点评:132
Java Object 通用方法 toString() 之 Integer.toHexString(),
toString()的源代码如下:public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
getClass() 返回类对象 ;getName() 以String形式返回类对象的名称(包换包名);Integer.toHexString(hashCode()) 以对象的哈希码为参数,以16进制无符号整数形式返回此哈希码的字符串表示形式;下面主要分析下Integer.toHexString()以下是其源码:public static String toHexString(int i) {
return toUnsignedString0(i, 4);
}
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val); // (1)
int chars = Math.max(((mag + (shift - 1)) / shift), 1); // (2)
char[] buf = new char[chars];
formatUnsignedInt(val, shift, buf, 0, chars); // (3)
// Use special constructor which takes over "buf".
return new String(buf, true);
}
(1) 这一步主要是为了计算val值对应的二进制数中除去首部0的个数后剩下的有效位数mag。 a.Integer.SIZE: int在jvm中占4个字节,共32位; b.首部0的个数:是指从左边第一个位置开始累加0的个数,一直加到第一个非零值; c.方法numberOfLeadingZeros() 就是计算首部0的个数。下面看看numberOfLeadingZeros()的源码,源码应用了二分查找,先把32位整形分为高16位和低16位查找非零数,在对高16位进行或低16位进行二分,以此类推,直到找到左边第一个非零值的位置。public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
// 初始首部0的个数:1 假定最高位有一个0,最后的时候会根据最高位是否位零补偿返回
int n = 1;
// 下面的代码主要是为了找出左边第一个非零值的位置
// 采用二分查找的方法,首先将 i 无符号右移16位后,有两种情况(a, b):
// a. 右移后 = 0,则第一个非零值出现在低16位,那么 i 首位至少有16个0(n=17),
// 同时将 i 左移16位后赋值给自己(将低16位移到了高16位,这样可以使两种保持同一的状态进行后续判断);
// b. 右移后!=0,则第一个非零值出现在高16位(n=1),继续在高16位中寻找;
// 将高16位继续分为 高8位和低8位进行判断,一直二分到还有两位的时候;
// 最后 i 无符号右移31位(结果要么是0要么是1),如果右移后为0,说明此时的最高位为0,无需补偿,直接返回 n;
// 如果右移后是1,则说明最高位不为0,需补偿,返回 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;
}
(2) int chars = Math.max(((mag + (shift - 1)) / shift), 1):计算 i 的有效二进制的位数所需要占的字节数(即对应的16进制的有效位数),toString()方法是以16进制返回,这里就以16进制来解释。根据二进制和16进制的转化关系可以知道,每4个二进制位代表一个16进制数,mag是有效的二进制位个数,所以想要计算需要的字节数可能遇到如下三种情况: a. mag=0,那么只需要一个字节即可;b.mag !=0, 是4的整数倍,则需要mag/4 个字节;
c.mag !=0,不是4的整数倍,则需要mag/4 +1 个字节;(mag + (shift - 1)) / shift 可以解决后面两种情况;Math.max(((mag + (shift - 1)) / shift), 1) 可以解决这三种情况。(3) 在toString() 方法中,formatUnsignedInt() 完成的功能就是将val值以16进制数形式存进buf数组中。先进行按位与运算,算出val的二进制中低四位对应的10进制的值,在 digits 数组中获取对应的16进制值,存进buf字节数组中;后将val无符号右移4位,保持在最低四位与mask进行按位与运算,在 digits 数组中获取对应的16进制值,存进buf字节数组中,以此循环,直到val=0或者charPos<=0后退出循环。
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[offset + --charPos] = Integer.digits[val & mask];
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}
相关文章
- 暂无相关文章
用户点评