设为首页 加入收藏

TOP

Java源码分析第3篇 - Java数值类型(一)
2014-11-24 07:25:35 】 浏览:7417
Tags:Java 源码 分析 3篇 数值 类型

这一篇主要介绍Java中经常使用的整数类型 - Integer

首先来说一下位运算,位运算应用是非常广的。无论是名企的笔试、面试,还是Java的源代码,这种应用随处可见。关于位运算我不想说太多,可以给大家推荐一篇非常不错的博文,地址如下:

http://blog.csdn.net/morewindows/article/details/7354571

同样,在Integer.java类的源代码中,Java的设计师们为了提高效率使用了大量的位运算,首先来看一个简单的进制转换源代码:

    //无符号整数 16进制,向右移动4位
    public static String toHexString(int i) {
        return toUnsignedString(i, 4);
    }
    //无符号整数 8进制,向右移动3位
    public static String toOctalString(int i) {
        return toUnsignedString(i, 3);
    }
   //无符号整数  2进制,向右移动2位
    public static String toBinaryString(int i) {
        return toUnsignedString(i, 1);
    }
    // 对无符号整数进行转换
    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;//i=i>>>shift
        } while (i != 0);

        return new String(buf, charPos, (32 - charPos));
    }
可以看一下对于10进制无符号整数的进制转换。由于缺少边界等的检查,所以toUnsignedString()方法并没有公开,而是提供了多个常用进制转换的方法。最后返回了转换后的字符串表示形式。至于 源码中为什么要定义一个32的字符数组后面将会分析到。

我们知道,Java中的int数值类型占用4个字节,有时候需要对表示一个int数值的4个字节做一些特殊的处理,如字节反转、位反转等,源代码如下:

 // 将4个字节的顺序进行逆转,并不是对位进行逆转
    public static int reverseBytes(int i) {
        return ((i >>> 24)           ) |
               ((i >>   8) &   0xFF00) |
               ((i <<   8) & 0xFF0000) |
               ((i << 24));
    }
    // 对位进行逆转
    public static int reverse(int i) {
        // HD, Figure 7-1
        i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
        i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
        i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
        i = (i << 24) | ((i & 0xff00) << 8) |
            ((i >>> 8) & 0xff00) | (i >>> 24);
        return i;
    }

大家可以好好研究一下如上的代码是怎么实现他们的功能的。继续看下面的两个方法:

   public static int highestOneBit(int i) {
        // HD, Figure 3-1
        i |= (i >>  1);
        i |= (i >>  2);
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);
        return i - (i >>> 1);
    }   
    public static int lowestOneBit(int i) {
        return i & -i;
    }

highestOneBit()作用是取 i 这个数的二进制形式最左边的最高一位且高位后面全部补零,最后返回int型的结果。而lowestOneBit()自然就是取最右边的第一位1,其前面全部置0后的结果。代码类中还提供了其他的一些方法,这些方法也大量用到了位操作,有兴趣的可以自己去看一下。
来看一下类中的其他重要的方法。

 // 如下的这些ASCII字符可能会表示为数字.26个字符和10个数字,加起来是36
    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'
    };

    public static String toString(int i, int radix) {
         // 基数的取值必须在一个范围
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;
        /* Use the faster version */
        if (radix == 10) {
            return toString(i);
        }
        char buf[] = new char[33];
        boolean negative = (i < 0);
        int charPos = 32;
        // 当i为一个正数时,变为负数
        if (!negative) {
            i = -i;
        }
        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = digits[-i];
        if (negative) {
            buf[--charPos] = '-';
        }
        return new String(buf, charPos, (33 - charPos));
    }
如上源代码片段首先定义了一个digits字符数组,这些数组是可以表示数值类型的。如在十六进制中,a可以表示10,b可以表示11一样,26个字母同样可以代表一个两位数的整数,加上10个数字后,共有32个字符可以用来表示数值。由此可知,Java中支持的最大进制为32,如果大于32,则按10进制进行处理。接下来有一个toString()方法,功能是将十进制的i转换为radix进制的数,并以字符串的形式进行返回。如下测试代码:
System.out.println(Integer.toString(13,19));
System.out.println(Integer.toString(173,29));
运行结果如下:d // 13 5s // 5*29+28

需要注意的是toString()方法的实现代码,可以看到对于一个有符号数i,都是转换为负数来进行进制转换的,这样可以统一进行有符号数的处理。那么可不可以转换为正数进行处理呢?这时候就需要考虑边界的问题了。举个例子,如byte类型,表示的最小整数为-128,而最大的整数为127,这时候将负数转换为正数就会超出类型所表示的范围,在这里的道理是一样的。
继续看另外一个toString()方法的源代码:

 public static String toString(int i) {
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        //举例:如果是9,这时size为1,而如果为-9时,为2,还要存储一个"-"号
        int size = (i < 0)   stringSize(-i) + 1 : stringSize(i);// 计算出保存整数需要的字符数组大小
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(0, size, buf);
    }
    //如下存储的是10进制的数
    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
        99999999, 999999999, Integer.MAX_VALUE };// 最大的MAX_VALUE为2147483647
    // Requires positive x
    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }
功能就是将一个有符号的整数转换为字符串,首先是将这个整数转换为字符数组,然后将这个字符数组转换为字符串,getChars()方法的源代码如下:

   final static char [] DigitTens = {
        '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
        '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
        '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
        '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
        '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
        '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
        '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
        '7', '7', '7', '7', '7', '7', '7', '7', '7', '
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇设计模式初探-Prototype模式 下一篇HibernateCRUD基础框架(1)-实体类

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目