JDK源码解读之toUnsignedString

我们知道,所有整数都是通过二进制编码的形式存储在内存中的。比如32位的整数,最高位是符号位,0代表正数,1代表负数。

那么怎么才能够将整数的二进制编码形式打印出来呢?Integer类提供了一个公有静态方法toBinaryString能够达到这一目的。我们来看看这段源码:

public static String toBinaryString(int i)
{
    return toUnsignedString(i, 1);
}

/**
 * Convert the integer to an unsigned number.
 */
private static String toUnsignedString(int i, int shift)
{
    char[] buf = new char[32];
    int charPos = 32;
    int radix = 1 << shift;
    int mask = radix - 1;
    do
    {
        buf[--charPos] = digits[i & mask];
        i >>>= shift;
     } while (i != 0);

     return new String(buf, charPos, (32 - charPos));
}    

可以看到,实际上是通过调用toUnsignedString方法来实现的。这段代码的精妙之处在于以下几点:

1. 掩码mask的计算。shift参数用于区分不同进制,比如二进制的shift=1,mask=1;八进制的shift=3,mask=7;十六进制的shift=4,mask=15。

2. 右移使用的是>>>而不是>>。位运算中的右移分为算术右移(>>)和逻辑右移(>>>)。在进行算术右移时,最高位补符号位;而在进行逻辑右移时,最高位补0。如果这里使用的算术右移,那么对于像-1这样的负数,不论进行多少次右移操作都不可能变成0,所以会造成死循环。

3. 使用的是do-while而不是while。这是一个极其重要的细节,如果使用的是while,那么对于i=0的场景则会返回空字符串。

时间: 2025-01-05 11:33:33

JDK源码解读之toUnsignedString的相关文章

jdk源码解读之ArrayList

直接上源码: 构造函数:     /**      * Constructs an empty list with an initial capacity of ten.      */     public ArrayList() {     this(10);     } 其实arrayList的本质是一个数据,只不过这个数组的大小可以变化.我们先来看下arraylist的数组是怎么定义的     /**      * Constructs an empty list with the sp

JDK源码解读之Integer(1)

本系列文章使用的JDK版本为jdk1.8.0_131,一些基础的知识储备:原码.反码.补码,移位,建议参考文章:<原码,反码,补码 详解><Java 源码学习系列(三)--Integer> Integer是我们开发过程中最常用的一个类,因此JDK的源码解读就从它开始吧.凡是对Java有点了解的都知道,Integer是int的包装类型,长度为32位.因此我们可以看到如下定义 //可表示的最小值:-2^31,至于为什么是这个数,上面的文章讲的很清楚了 @Native public st

HashTable的故事----Jdk源码解读

HashTable的故事 很早之前,在讲HashMap的时候,我们就说过hash是散列,把...弄碎的意思.hashtable中的hash也是这个意思,而table呢,是指数据表格,也就是说hashtable的本意是指,一份被数据被打散,分散在各处的数据表格. HashTable,作为jdk中,极早提供的容器类(jdk1.0),同时是支持数据并发的类,其在项目中的使用却并不是很广泛.在我所经历的项目中,开发人员往往喜欢使用hashMap然后再通过锁,创造出线程安全的环境.即使是后来推出concu

HashSet的故事----Jdk源码解读

Hash,我们在说HashMap的时候,已经知道Hash是散列,Map是映射了. 那么Set又是什么呢 ? 先来看看Set的翻译是什么 n. [数] 集合:一套:布景:[机] 装置 这里Set所取的含义是集合.而且是数学概念上的集合.数学概念上的集合有什么特点呢?那就是Set中所有的元素不能重复.所以HashSet的意思就是以散列的形式维持一套不会有重复元素的集合. 接下来我们看看HashSet是怎么被Jdk实现的吧.(其实逻辑非常简单.) 类的声明: hashSet 继承自AbstractSe

JDK 源码解读之 Set接口

public interface Set<E> extends Collection<E> { //Set很简单,扩展了Collection Set<E> 和 Collection<E> 都带了<E>,是泛型接口.什么是泛型类,泛型接口呢?Oracle官方文档上是这么说的: A generic class is defined with the following format: class name<T1, T2, ..., Tn>

JDK 源码解读之 ArrayList

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 文档中提到:size isEmpty get set iterator listIterator 操作,是( run in constant time), add操作是(run in amortized constant time),而 其他

JDK 源码解读之 Number类

public abstract class Number implements java.io.Serializable { Number类有修饰符 abstract .表明Number类定义了一些方法,并没有具体实现,需要子类自己实现,关于abstract ,quaro上一个答案写的很清晰: The "abstract" Keyword The keyword abstract can be used on classe declaration. For example abstra

Java之ArrayList源码解读(JDK 1.8)

java.util.ArrayList 详细注释了ArrayList的实现,基于JDK 1.8 . 迭代器SubList部分未详细解释,会放到其他源码解读里面.此处重点关注ArrayList本身实现. 没有采用标准的注释,并适当调整了代码的缩进以方便介绍 import java.util.AbstractList; import java.util.Arrays; import java.util.BitSet; import java.util.Collection; import java.

JDK源码分析之concurrent包(三) -- Future方式的实现

上一篇我们基于JDK的源码对线程池ThreadPoolExecutor的实现做了分析,本篇来对Executor框架中另一种典型用法Future方式做源码解读.我们知道Future方式实现了带有返回值的程序的异步调用,关于异步调用的场景大家可以自行脑补Ajax的应用(获取返回结果的方式不同,Future是主动询问获取,Ajax是回调函数),这里不做过多说明. 在进入源码前,首先来看下Future方式相关的API: 接口Callable:有返回结果并且可能抛出异常的任务: 接口Future:表示异步