J2se源码剖析 基本数据类型Integer

来源:互联网 发布:java多线程调用方法 编辑:程序博客网 时间:2024/06/05 17:46

大家都知道int 是基本数据类型而Integer则是int的包装类,为什么要为基本数据类型提供包装类呢?这里我只说一个最基本的原因 “为了在各种类型间转化,通过各种方法的调用。否则 你无法直接通过变量转化”,这只是其一,其余的我就不一一赘述了,下面让我们来一下Integer的源码

    public static final int   MIN_VALUE = 0x80000000; //Integer中所能存储的最大值,即2的31次方减一。    public static final int   MAX_VALUE = 0x7fffffff; //Integer中所能存储的最小值,即负2的31次方 减一。    public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); //原始类型int的Class实例。    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'         }; //所有可能的将数字表示为字符串的字符集合。    //返回第二个参数所指定的进制数的第一个参数的字符串表示形式

我们可以通过上面的代码看到Integer继承了Number,对于Number这个类这里就不讲了,并且实现了Comparable接口,并且声明了int的最大值与最小值,声明了一个digits数组,用以数据类型转换

下面就是toString方法 :

我们知道这个toString方法有两个重载方法一个方法只传入一个int值,另一个方法传入两个int值,在这里我们先讲解传入两个参数的toString方法,第一个参数是我们需要转成String的int值,第二个参数radix则是需要将这个int值转换成几进制(2 - 36),然后转换成字符串


下面是代码 :

   public static String toString(int i, int radix) {        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)         //判断radix是否在2到36之间,如果超过了就将radix = 10,让下面判断等于10 直接调用另一个toString方法直接转换成10进制的字符串            radix = 10;        /* Use the faster version */                 if (radix == 10) {                         return toString(i);                 }        /*        如果传入的radix在 2到36之间的话,就直接进行下面的进制转换        */        char buf[] = new char[33];                 boolean negative = (i < 0);   //要转化的值为负数时,将negative设置为true         int charPos = 32;        if (!negative) {                         i = -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));   //返回一个字符串      }

这就是 toString(int i ,radix)了,现在我们来看一下另一种只传入一个参数的toString方法,

 public static String toString(int i) {        if (i == Integer.MIN_VALUE)            return "-2147483648";//如果传入的是inteager的最小值也就是 -2的31的次方  直接返回最小值        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); //如果i为负数,则字符串长度要加1。        char[] buf = new char[size];        getChars(i, size, buf); //获取i中字符的集合。        return new String(buf, true);//返回字符串    }

现在来讲解,Integer的parseInt方法,这个方法我们经常性的用来进行类型转换,并且这个方法还重载了两个,一个是传入一个字符串将其转换为int值,还有一个就是传入一个字符串和radix,相信radix这个变量我们已经很熟悉了,就toString 的radix是一样的,代表着几进制,下面让我们来了解一下这个函数

    public static int parseInt(String s, int radix)                throws NumberFormatException    {        if (s == null) { //调用方法前检查参数的正确性。            throw new NumberFormatException("null");        }        if (radix < Character.MIN_RADIX) {            throw new NumberFormatException("radix " + radix +                                            " less than Character.MIN_RADIX");//检查radix是否在 2 到 36之间        }        if (radix > Character.MAX_RADIX) {            throw new NumberFormatException("radix " + radix +                                            " greater than Character.MAX_RADIX");        }        int result = 0;        boolean negative = false;        int i = 0, len = s.length(); //i表示当前遍历的s的位数        int limit = -Integer.MAX_VALUE; //设置最小值为负的Integer的最大值        int multmin;        int digit;        if (len > 0) { //如果字符串长度大于0,则进行转换            char firstChar = s.charAt(0); //获取第一位字符            //在第一位字符小于'0'的情况下,判定是否含有符号'+'、'-'            if (firstChar < '0') { // Possible leading "+" or "-"                 if (firstChar == '-') { //为负数的情况                    negative = true;                    limit = Integer.MIN_VALUE; //不能小于Integer的最小值                } else if (firstChar != '+') //不为'-'时,如果不为'+',则表示符号错误。                    throw NumberFormatException.forInputString(s);                //如果字符串的长度等于1,且这个字符小于'0',则表示该字符串仅为一个符号,抛出异常                if (len == 1) // Cannot have lone "+" or "-"                    throw NumberFormatException.forInputString(s);                i++;            }            multmin = limit / radix;            while (i < len) { //进行进制的转换                // Accumulating negatively avoids surprises near MAX_VALUE                digit = Character.digit(s.charAt(i++),radix);                if (digit < 0) {                    throw NumberFormatException.forInputString(s);                }                if (result < multmin) {                    throw NumberFormatException.forInputString(s);                }                result *= radix;                if (result < limit + digit) {                    throw NumberFormatException.forInputString(s);                }                result -= digit;            }        } else {            throw NumberFormatException.forInputString(s);        }        return negative ? result : -result; //根据符号返回正数还是负数    }

这就是传入两个参数的parseInt了,接下来只传入一个参数parseInt,相信大家已经知道了,非常简单的直接调用了parseInt(s,10);然后返回

    public static int parseInt(String s) throws NumberFormatException {        return parseInt(s,10);    }

接下来要讲的就是Inteager.valueOf()了,这个方法相信已经很多用过了,对的,没错他的功能就是将String转换成Integer对象,关于这个方法

(1)调用Integer类中的静态方法valueOf(String)
(2)valueOf方法将传入的参数String转化为int型值
(3)返回该值,如果String并不是纯粹由数字构成即无法转化为数字,则抛出NumberFormatException

当然这个方法也有三个重载方法,valueOf(int i)直接返回一个实例 valueOf(String s, int radix) 调用parseInt 转换成int值 valueOf(String s) 调用Integer.valueOf(parseInt(s, 10)); 下面是代码 *

 public static Integer valueOf(int i) {        assert IntegerCache.high >= 127; //断言Integer缓存中的上届必须大于或等于127        if (i >= IntegerCache.low && i <= IntegerCache.high) //如果i在Integer缓存中,则直接取出            return IntegerCache.cache[i + (-IntegerCache.low)];        return new Integer(i); //否则,直接创建一个实例    }  public static Integer valueOf(String s, int radix) throws NumberFormatException {        return Integer.valueOf(parseInt(s,radix));     }    public static Integer valueOf(String s) throws NumberFormatException {        return Integer.valueOf(parseInt(s, 10));    }

好了 讲的差不多了,下面是完整的代码

import java.util.Properties;public final class Integer extends Number implements Comparable<Integer> {    public static final int   MIN_VALUE = 0x80000000; //Integer中所能存储的最大值,即231-1。    public static final int   MAX_VALUE = 0x7fffffff; //Integer中所能存储的最小值,即2-31。    public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); //原始类型int的Class实例。    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;        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));         }    public static String toHexString(int i) {        return toUnsignedString(i, 4);    }    public static String toOctalString(int i) {        return toUnsignedString(i, 3);    }    public static String toBinaryString(int i) {        return toUnsignedString(i, 1);    }    //转换int类型为无符号的字符串    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));    }    //十位数上的字符集    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', '7',        '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',        '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',        } ;    //个位数上的字符集    final static char [] DigitOnes = {        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',        } ;    public static String toString(int i) {        if (i == Integer.MIN_VALUE)            return "-2147483648";        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); //如果i为负数,则字符串长度要加1。        char[] buf = new char[size];        getChars(i, size, buf); //获取i中字符的集合。        return new String(buf, true);    }    static void getChars(int i, int index, char[] buf) {        int q, r;        int charPos = index;        char sign = 0;        if (i < 0) { //如果i为负数,则设置i的符号字符为'-'。            sign = '-';            i = -i;        }        // Generate two digits per iteration        while (i >= 65536) { //如果i大于65536,则每一次都获取十位和个位上的数字对应的字符。            q = i / 100;        // really: r = i - (q * 100);            r = i - ((q << 6) + (q << 5) + (q << 2)); //每次获得i的最后两位数            i = q;            buf [--charPos] = DigitOnes[r]; //存储r中在个位数集合中对应的字符            buf [--charPos] = DigitTens[r]; //存储r中在十位数集合中对应的字符        }        // Fall thru to fast mode for smaller numbers        // assert(i <= 65536, i);        for (;;) { //i<65536的情况            q = (i * 52429) >>> (16+3);            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ... //每次获得i的最后两位数            buf [--charPos] = digits [r];            i = q;            if (i == 0) break;        }        if (sign != 0) {            buf [--charPos] = sign; //设置符号        }    }    //定义sizeTable表示int中每个位数中最大的数,用于简便确定int数的长度。    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,                                      99999999, 999999999, Integer.MAX_VALUE };    //使用上面的sizeTable定义来确定int数的字符串表示长度。               static int stringSize(int x) {        for (int i=0; ; i++)            if (x <= sizeTable[i])                return i+1;    }    public static int parseInt(String s, int radix)                throws NumberFormatException    {        if (s == null) { //防御性编程,调用方法前检查参数的正确性。            throw new NumberFormatException("null");        }        if (radix < Character.MIN_RADIX) {            throw new NumberFormatException("radix " + radix +                                            " less than Character.MIN_RADIX");        }        if (radix > Character.MAX_RADIX) {            throw new NumberFormatException("radix " + radix +                                            " greater than Character.MAX_RADIX");        }        int result = 0;        boolean negative = false;        int i = 0, len = s.length(); //i表示当前遍历的s的位数        int limit = -Integer.MAX_VALUE; //设置最小值为负的Integer的最大值        int multmin;        int digit;        if (len > 0) { //如果字符串长度大于0,则进行转换            char firstChar = s.charAt(0); //获取第一位字符            //在第一位字符小于'0'的情况下,判定是否含有符号'+'、'-'            if (firstChar < '0') { // Possible leading "+" or "-"                 if (firstChar == '-') { //为负数的情况                    negative = true;                    limit = Integer.MIN_VALUE; //不能小于Integer的最小值                } else if (firstChar != '+') //不为'-'时,如果不为'+',则表示符号错误。                    throw NumberFormatException.forInputString(s);                //如果字符串的长度等于1,且这个字符小于'0',则表示该字符串仅为一个符号,抛出异常                if (len == 1) // Cannot have lone "+" or "-"                    throw NumberFormatException.forInputString(s);                i++;            }            multmin = limit / radix;            while (i < len) { //进行进制的转换                // Accumulating negatively avoids surprises near MAX_VALUE                digit = Character.digit(s.charAt(i++),radix);                if (digit < 0) {                    throw NumberFormatException.forInputString(s);                }                if (result < multmin) {                    throw NumberFormatException.forInputString(s);                }                result *= radix;                if (result < limit + digit) {                    throw NumberFormatException.forInputString(s);                }                result -= digit;            }        } else {            throw NumberFormatException.forInputString(s);        }        return negative ? result : -result; //根据符号返回正数还是负数    }    public static int parseInt(String s) throws NumberFormatException {        return parseInt(s,10);    }    public static Integer valueOf(String s, int radix) throws NumberFormatException {        return Integer.valueOf(parseInt(s,radix));     }    public static Integer valueOf(String s) throws NumberFormatException {        return Integer.valueOf(parseInt(s, 10));    }    //内部字符缓存类    private static class IntegerCache {        //缓存的下界,-128,不可变          static final int low = -128;        //缓存上界,暂为null        static final int high;        static final Integer cache[]; //利用数组来缓存        static {            // high value may be configured by property            // 缓存上届,可以通过JVM属性来配置            int h = 127;            String integerCacheHighPropValue =                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");            //获取            if (integerCacheHighPropValue != null) {                int i = parseInt(integerCacheHighPropValue);                i = Math.max(i, 127);                // Maximum array size is Integer.MAX_VALUE                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);            }            high = h;            //获取Integer中所有能保存的数据            cache = new Integer[(high - low) + 1];            int j = low;            //缓存所有Integer的数据            for(int k = 0; k < cache.length; k++)                cache[k] = new Integer(j++);        }        private IntegerCache() {}    }    public static Integer valueOf(int i) {        assert IntegerCache.high >= 127; //断言Integer缓存中的上届必须大于或等于127        if (i >= IntegerCache.low && i <= IntegerCache.high) //如果i在Integer缓存中,则直接取出            return IntegerCache.cache[i + (-IntegerCache.low)];        return new Integer(i); //否则,直接创建一个实例    }}
6 0
原创粉丝点击