JDK源码解读第八章:java.lang.Integer

JDK源码解读第八章:java.lang.Integer可以看到Integer类继承了Number类,而又不是抽象类,自然要重写Number类中的xxxValue方法。另外Integer类实现了Comparable接口,Comparable是一个接口,该接口定义类的自然顺序,实现该接口的类就可以按这种方式排序,一般情况下如果某类对象…

Integer

1.Integer声明

public final class Integer extends Number implements Comparable<Integer> {}

可以看到Integer类继承了Number类,而又不是抽象类,自然要重写Number类中的xxxValue方法。另外Integer类实现了Comparable接口,Comparable是一个接口,该接口定义类的自然顺序,实现该接口的类就可以按这种方式排序,一般情况下如果某类对象自身具有比较的特性就可以实现该接口,比如这里的Integer代表的是一种数,而数本身就具有比较的特性,就可以实现该接口。

2.Integer边界值

	@Native public static final int   MIN_VALUE = 0x80000000;
    @Native public static final int   MAX_VALUE = 0x7fffffff;

0x80000000 的2进制是1000,0000,0000,0000,0000,0000,0000,0000第一位是符号位,表示负的,后边是数值位,因为是负数,所以要取反计算,000,0000,0000,0000,0000,0000,0000,0000取反后111,1111,1111,1111,1111,1111,1111,1111,二进制是由补码表示,取补码为1000,0000,0000,0000,0000,0000,0000,0000,转为十进制是2^31,等于2147483648。因为是负数, 所以,0x80000000是-2147483648,int的最小值。
0x7fffffff 的2进制是0111,1111,1111,1111,1111,1111,1111,1111第一位是符号位,表示正数,正数反码和补码都等于原码为0111,1111,1111,1111,1111,1111,1111,1111,十进制是2^31-1, 所以,0x7fffffff是2147483647,int的最大值。

3.数组属性

	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'
	};
	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',
    } ;
	final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

digits数组用于表示所有可能出现的字符,所以这里需要有36个字符才能表示所有不同进制的数字 DigitTens和DigitOnes两个数组也很好理解,它们主要用于获取0到99之间某个数的十位和个位,比如36,通过DigitTens数组直接取出来十位为3,而通过DigitOnes数组取出来个位为6。 sizeTable数组主要用在判断一个int型数字对应字符串的长度。避免了使用除法或求余等操作,以提高效率。

4.toString(int i, int radix)

	public static String toString(int i, int radix) {
    	//如果传入的radix小于2或者大于36,赋值为10
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;

        /* Use the faster version */
        if (radix == 10) {
            return toString(i);
        }

        //创建一个用于存放转换为指定字符的字符型数组,interger最大32位加上符号位
        char buf[] = new char[33];
        boolean negative = (i < 0);
        int charPos = 32;

		//全部转换位负数
        if (!negative) {
            i = -i;
        }

        while (i <= -radix) {
        	//i和进制取余为第一个数组数值,一直循环到不能循环为止
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        //将最后一个余数添加到数组
        buf[charPos] = digits[-i];

		//如果为负数添加符号
        if (negative) {
            buf[--charPos] = '-';
        }

		//buf转化为字符串
        return new String(buf, charPos, (33 - charPos));
    }
    
    public static String toString(int i) {
    	//如果传入的值等于最小值直接返回
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        //如果是负数,size等于stringSize(-i) + 1,加1为多一个符号位,否则等于 stringSize(i)
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        //计算出大小后。创建一个固定大小的char数组。
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
    }
    
    //利用之前说的数组值,直接计算大小,比如小于等于9肯定为1位数,依次类推,这样避免做除法带来的其他问题。
    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }
    
    static void getChars(int i, int index, char[] buf) {
        int q, r;
        int charPos = index;
        char sign = 0;

        if (i < 0) {
            sign = '-';
            i = -i;
        }

        // Generate two digits per iteration
        //如果大于65536
        while (i >= 65536) {
        	//q等于i整除,其实就是取数的后两位之前的数
            q = i / 100;
        // really: r = i - (q * 100);
        	//明确的提示的就是r = i - (q * 100),结果为参数的最后两位
            r = i - ((q << 6) + (q << 5) + (q << 2));
            i = q;
            //一次插入最后两位的十位数和个位数,这个地方很巧妙的运用了数组,而没有使用除法和取余。
            buf [--charPos] = DigitOnes[r];
            buf [--charPos] = DigitTens[r];
        }

        // Fall thru to fast mode for smaller numbers
        // assert(i <= 65536, i);
        //不管条件一直循环
        for (;;) {
        	//这个操作最终结果其实就是i/10
            q = (i * 52429) >>> (16+3);
            //这是i*10
            r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
            //结果r为i的个位数,用数组取值插入buf
            buf [--charPos] = digits [r];
           	//一直循环完所有个位数,最后一次i/10为0,跳出循环
            i = q;
            if (i == 0) break;
        }
        //如果为负数,插入数组第一个值为-号
        if (sign != 0) {
            buf [--charPos] = sign;
        }
    }

这个方法用于对参数转换为指定进制的字符串,里面有一些简单的设计比较可以学习。比如数组个位数和十位数,位运算都避免了除法操作。

5.toHexString(int i)

	//转换为16进制
	public static String toHexString(int i) {
        return toUnsignedString0(i, 4);
	}
	//转换为8进制
	public static String toOctalString(int i) {
        return toUnsignedString0(i, 3);
	}
	//转换为2进制
	public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
	}
    
    private static String toUnsignedString0(int val, int shift) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        //计算数组大小
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];

        formatUnsignedInt(val, shift, buf, 0, chars);

        // Use special constructor which takes over "buf".
        return new String(buf, true);
    }
    
    //在指定 int 值的二进制补码表示形式中最高位(最左边)的 1 位之前,返回零位的数量
    public static int numberOfLeadingZeros(int i) {
        // HD, Figure 5-6
        if (i == 0)
            return 32;
        //例子:假设有如下二进制数A是0000 1111 1111 1111 1111 1111 1111 1111,
        int n = 1;
        //如果高16位全部为0,n为17,低16位移动到高16位,例子不进if
        if (i >>> 16 == 0) { n += 16; i <<= 16; }
        //如果高24位全部为0,n为17,低24位移动到高24位,例子不进if
        if (i >>> 24 == 0) { n +=  8; i <<= 8; }
        //如果高28位全部为0,n为17,低28位移动到高28位,例子进if,n为4+1=5,左移4位,所以要A变成 1111 1111 1111 1111 1111 1111 1111 0000
        if (i >>> 28 == 0) { n +=  4; i <<= 4; }
        //如果高30位全部为0,n为17,低30位移动到高16位,例子不进if
        if (i >>> 30 == 0) { n +=  2; i <<= 2; }
        //无符号右移31位后变成0000 0000 0000 0000 0000 0000 0000 0001,十进制表示为1,n -= i >>> 31;n -= 1;n = n - 1 = 5-1 = 4,说明前导0的个数是4
        n -= i >>> 31;
        return n;
    }
    
    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;
    }

主要是用于10进制转换为其他进制的数据。

6.parseInt(String s, int radix)

	public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
    	// 第一步、判断字符串参数是否为null 
        if (s == null) {
            throw new NumberFormatException("null");
        }
        // 第二步,判断基数是否小于最小基数 为2
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
        // 第三步,判断基数是否大于最大基数 为36
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }
        int result = 0;
        // 标识,是否为负数,默认false
        boolean negative = false;
         // 字符串转换为char数组后的 下标和数组长度
        int i = 0, len = s.length();
        int limit = -Integer.MAX_VALUE;
        int multmin;
        int digit;
        // 第四步,判断字符串长度是不大于0
        if (len > 0) {
            // 取第一个字符
            char firstChar = s.charAt(0);
            / 字符ASCII是否小于'0' ,可能为 '+' '-' , 如果不是<'0' ,则为数组 ,略过该if{}
            if (firstChar < '0') { // Possible leading "+" or "-"
            	// 如果第一个字符是'-' ,说明是负数,则负数标识改为true ,限制改为最小标识
                if (firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+')
                	// 如果第一个字符不是'-' 也不是'+' ,异常
                    throw NumberFormatException.forInputString(s);
                // 第一字符<'0' 且长度为1  则不是数字 异常   
                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                i++;
            }
            multmin = limit / radix;
            // 遍历字符串转为的字符数组,将每一个字符转为10进制值,并拼接,比如输入“123” 10进制数
            while (i < len) {
                //获取字符转换成对应进制的整数,如上,这里第一次循环获取1
                //第二次循环获取2
                //第三次循环获取3
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                //判断,在追加后一个数字前,判断其是否能能够在继续追加数字,比如multmin = 123
                那么再继续追加就会变为123*10+下一个数字,就会溢出
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                //第一次循环   result = 0;
                //第二次循环   result = -10;
                //第三次循环   result = -120;
                result *= radix;
                //用于判断下一个准备追加的数字是否可以追加,比如result现在是120,那么,如果digit是5,
             那么追加后就会变为125,已经超过123的限制了,注意这里是limit而不是multmin
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                /第一次循环 result = -1;
                //第二次循环 result = -12;
                //第三次循环 result = -123;
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        //negative 值为false,所以 -result = -(-123) = 123  返回结果
        return negative ? result : -result;
	}

这个方法用于对指定参数的字符串转换为指定进制的数字。

7.valueOf(String s, int radix)

	public static Integer valueOf(String s, int radix) throws NumberFormatException {
    	//字符串转化为数字
        return Integer.valueOf(parseInt(s,radix));
    }
    
    public static Integer valueOf(int i) {
    	//如果返回的值在缓存中,直接获取缓存中数据
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
         //不在则新建一个对象
        return new Integer(i);
    }
    
    	//初始化缓存
        private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            //获取jvm配置的上限大小
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    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);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            //循环存放缓存数据
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

这个方法用于对指定参数的字符串转换为指定进制的数字对象,当中部分数据会中缓存中获取,不用新建对象。

8.byteValue()

	public byte byteValue() {
        return (byte)value;
    }

	public short shortValue() {
        return (short)value;
    }
	
    public int intValue() {
        return value;
    }
    
    public long longValue() {
        return (long)value;
    }
    
    public float floatValue() {
        return (float)value;
    }
    
    public double doubleValue() {
        return (double)value;
    }

整型对象转化基本数据类型。

9.hashCode()

	@Override
    public int hashCode() {
        return Integer.hashCode(value);
    }
    
    public static int hashCode(int value) {
        return value;
    }

重写hashcode直接返回对象的基本数据类型的值。

10.equals(Object obj)

	public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

重写equals,比较对象为Integer对象并且值相等即对象相等。其他方法就不一一分析了,有些比较简单,有些使用场景不多,有兴趣的可以读者自己去看看。

今天的文章JDK源码解读第八章:java.lang.Integer分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16821.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注