JDK Integer.toHexString方法源码阅读

本文详细解析了Java中整型转化为十六进制的底层实现过程,包括计算前导零个数、确定转换后长度及核心转换方法。通过具体步骤与代码示例,帮助读者理解toHexString方法的工作原理。
public static String toHexString(int i) {
    return toUnsignedString0(i, 4);
}

         底层方法实际上是一个二进制、八进制和十六进制通用的一个方法

/**
 * Convert the integer to an unsigned number.
 */
 private static String toUnsignedString0(int val, int shift) {
    // assert shift > 0 && shift <=5 : "Illegal shift value";
    //通过Integer最大的长度减去开头0的个数,计算输入的数值真正占的位数
    int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
    //计算真正占用的位转换后,所占用的位数
    int chars = Math.max(((mag + (shift - 1)) / shift), 1);
    //根据计算得出的长度创建一个最终返回的char[]数组
    char[] buf = new char[chars];

    //算是真正的将Integer类型转换成需要进制的方法
    formatUnsignedInt(val, shift, buf, 0, chars);

    //使用char[]数组创建一个String类型返回
    // Use special constructor which takes over "buf".
    return new String(buf, true);
 }

 参数:

  • val:想要转换的Integer值
  • shift:转换的位数,二进制:1;八进制:3;十六进制:4     

步骤具体详解

1、计算最前面站位0的个数

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;
}

2、获取转换后占用的长度

//计算真正占用的位转换后,所占用的位数
int chars = Math.max(((mag + (shift - 1)) / shift), 1);

              a、shift - 1的作用:将位数向上取整

例:
//如果真正的长度为6,转换成十六进制,不加(shift - 1)时
6/4 = 1
//小数部分被省略了,但其实我们需要两位来装长度为六的数据
//添加了(shift - 1)后
(6+(4-1))/4 = 2
//就将计算结果向上取整

             b、Math.max(int a, int b);比较最大值

3、真正的转换方法

/**
 * 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;
    //获取基数,二进制为2,八进制为8,十六进制为16
    int radix = 1 << shift;
    //根据基数获取当前进制的最大数,用于格式化。二进制:0b1,八进制:0777,十六进制:0xFFFF
    int mask = radix - 1;
    //进行循环将内容添加进char[]数组
    do {
        //将Integer的最低四位根据最大值格式化,然后根据格式化的值去上面的char[]数组中取值,
        //再将取到的char按照倒叙存入目标数组buf中
        buf[offset + --charPos] = Integer.digits[val & mask];
        //无符号右移进制的个数
        val >>>= shift;
    //判断当前val是否为0并且存写长度是否为零,如果val不为零且存写长度也不为0,继续循环
    } while (val != 0 && charPos > 0);

    //返回剩余的存写长度
    return charPos;
}

参数

  • val:需要转换的Integer类型值
  • shift:几位转换成一个,二进制:1;八进制:3;十六进制:4;
  • buf:目标数组,转换后的数据存储的地方
  • offset:偏移量,从buf存储的偏移量
  • len:存写的长度

              a、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'
};

4、创建字符串类型返回

return new String(buf, true);
  1. 所使用的构造方法的访问级别为缺省,包下访问
  2. value:表示需要转换的char[]数组
  3. share:标识符号,为了和常用的公共的构造器(如下图)区分开,值常为true
  4. 方法直接将char[]数组的引用赋值给value,

    好处

  1. 和公共方法的Arrays.copyOf()比,速度更快

    缺点

  1. 因为是直接将引用赋值给value,所以当char[]数组改变时,String的内容也会一同改变,不符合String一旦创建就不能改变的原则,所以为访问修饰符为缺省

总结

        本质上toHexString方法,其实就是根据要转换的位数变成脚标,然后去一个特定的数组中取数,然后封装成String返回

buf[offset + --charPos] = Integer.digits[val & mask];

        其他的所有代码都是为这个做准备

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值