zoukankan      html  css  js  c++  java
  • JDK源码分析 – Integer

    Integer类的申明

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

    Integer用于对int类型数值的封装,并提供一些int类型数据操作的方法,Integer继承自Number类,Number是JDK的一个代表数值的超类,提供一些用于不同数值之间类型转换方法,常见的数值类型Double、Float等都继承自Number

    Integer还实现了Comparable接口,主要用于Integer对象之间比较。

    Integer字段、属性说明

    Integer是对int型数值的封装,int型,占4个字节(JDK中定义占4字节),每个字节8位因次是32位,再除去一个符号位,因此范围是-2^31~2^31-1

    下面列举几个重要的字段解释一下:

        /**
         *代表Integer封装的int整形数值 
         */
        private final int value;
        
        /**
         *限制Integer对象存放最小值 -2^31
         */
        @Native public static final int   MIN_VALUE = 0x80000000;
    
        /**
         * //限制Integer对象存放最大值 2^31-1
         */
        @Native public static final int   MAX_VALUE = 0x7fffffff;
    
    
        /**
         *表示int二进制补码形式的值的位数。
         */
        @Native public static final int SIZE = 32;
    
        /**
         * 用于以int二进制补码形式表示值的字节数32/8 = 4字节
         */
        public static final int BYTES = SIZE / Byte.SIZE;

    Integer 部分方法分析

    Integer类内部提供了很多方法,用于数值转换等操作,下面仍然是列举几个经常用到的分析一下实现过程:

    构造函数Integer(String s)

    /**
     * 构造函数,允许传入一个字符串,通过内部函数parseInt尝试将其转成10进制int型数值,默认转成10进制,如果传入的String无法转换成Int则跑出异常
     */
    public Integer(String s) throws NumberFormatException {
            this.value = parseInt(s, 10);
    }

    int parseInt(String s, int radix)方法

    将字符串参数解析为指定的几进制带符号整数,转换失败抛出异常,string参数:将要转换为数值的字符串,int参数:代表需要转换的是几进制数值

    JDK源码注释中给出一些示例:

        /**
         * JDK源码注释中的示例: 
         * <p>Examples:
         * <blockquote><pre>
         * parseInt("0", 10) returns 0
         * parseInt("473", 10) returns 473
         * parseInt("+42", 10) returns 42
         * parseInt("-0", 10) returns 0
         * parseInt("-FF", 16) returns -255
         * parseInt("1100110", 2) returns 102
         * parseInt("2147483647", 10) returns 2147483647
         * parseInt("-2147483648", 10) returns -2147483648
         * parseInt("2147483648", 10) throws a NumberFormatException
         * parseInt("99", 8) throws a NumberFormatException
         * parseInt("Kona", 10) throws a NumberFormatException
         * parseInt("Kona", 27) returns 411787
         */
        public static int parseInt(String s, int radix)
                    throws NumberFormatException
        {
            /*
             * WARNING: This method may be invoked early during VM initialization
             * before IntegerCache is initialized. Care must be taken to not use
             * the valueOf method.
             */

    //字符串为空直接异常 if (s == null) { throw new NumberFormatException("null"); } //判断radix合法性,Integer内部允许2进制-36进制之间转换 //为什么是36进制? 看个示例 // Integer.parseInt("A", 16) = 10     // Integer.parseInt("a", 16) =10     // 上面可以看出不区分大小写,是不是10个数字+26个母? 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; //符号,正数or负数 int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; int multmin; int digit; //字符串长度大于0 if (len > 0) { char firstChar = s.charAt(0); if (firstChar < '0') { // Possible leading "+" or "-" 判断第一个字符是不是符号为=位 if (firstChar == '-') { negative = true; //确定是负数标志 limit = Integer.MIN_VALUE; //限制最小值 } else if (firstChar != '+') throw NumberFormatException.forInputString(s); //符号位既不是+也不是-,抛异常 if (len == 1) // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); //长度是1,只有符号位,没有数值,抛异常 i++; } multmin = limit / radix; //遍历字符转,从最高位开始,整个过程以负数计算,逐位乘以单位制,最后再修正符号位,以10进制数123为例。转换过程如下 // result = -1 // result = -1*10-2 = -12 // result = -12*10-3 = -123 while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++),radix); //将字符转换为radix进制数值,比如Character.digit(‘c’,16) = 12 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相关方法也都是调用这个最基础的方法进行转换。

    Integer valueOf(int i)方法

    返回指定int值的Integer实例,如果Integer不需要新实例,可优先使用此方法,而不是构造函数,因为此方法会缓存经常请求的值的Integer实例。该方法将始终缓存-128至127(含)范围内的值,并可缓存此范围之外的其他值

    public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
    }

     Valueof方法内部使用了IntegerCache,判断如果数值在[IntegerCache.low, IntegerCache.high]这个范围内,则从缓存中读取,否则调用构造函数创建一个Integer实例

    private static class IntegerCache {
            static final int low = -128; //最小值 -128
            static final int high;       //最大值
            static final Integer cache[];
    
    //静态代码块,在Integer类加载时就已经缓存好
            static {
                // high value may be configured by property
                int h = 127;  //最大值 127
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");  //读取最大值配置参数
                if (integerCacheHighPropValue != null) {
                    try {
                        int i = parseInt(integerCacheHighPropValue);
                        i = Math.max(i, 127);               //在配置参数和默认h中取最大值
                        // 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++); //缓存integer对象
    
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;  
            }
    
            private IntegerCache() {}
        }

    Valueof()方法完成将int型转换成Integer对象,其实就是一个装箱操作,Integer类型也可以直接赋值一个int数值:Integer integer = 100 这其实就是通过调用valueof()方法完成的。

    相对应的方法:int intValue() 获取Integer对象内部value值,其实就是完成一个拆箱操作

    public int intValue() {
            return value;
        }

    下面给出一组测试示例,通过对Integer对比分析一下Integer对象的装箱拆箱和IntegerCache缓存:

            Integer integer0 = Integer.valueOf(1);   //IntegerCache缓存中读取
            Integer integer1 = new Integer(1);        //创建新实例
            Integer integer2 = new Integer(1);        //创建新实例
            System.out.println(integer1.equals(integer2)); //true Integer.equal内部实现并不是比较两个Integer对象的引用,而是比较Integer.value值是否相等
    System.out.println(integer1==integer2); //false integer1和integer2是两个不同的对象,引用不一样 Integer integer3 = 1; Integer integer4 = 1; System.out.println(integer3 == integer4);//true,integer3和integer4都完成装箱,从IntegerCache中取出相同的实例 Integer integer8 = 128; Integer integer9 = 128; System.out.println(integer8 == integer9);//false,integer8和integer9都完成装箱,New Integer(128)==new Integer(128) System.out.println(integer3 == integer1);//false,integer3通过调用valueof做了装箱操作 实际相当于 Integer.valueOf(1)==integer1 System.out.println(integer3 == integer0);//true,integer3通过调用valueof做了装箱操作 实际相当于 Integer.valueOf(1)==integer0 ,都从IntegerCache缓存中读取 int integer5 = 1; Integer integer6 = new Integer(1); System.out.println(integer5 == integer5);//true 当Integer对象和int比较时,Integer对象调用intValue完成自动拆箱,转换为int,相当于两个int型比较 Integer integer7 = 1; System.out.println(integer7==integer5); //true integer7先装箱,比较时又做了拆箱操作

    Integer和int的区别

             Integer是对int型封装后的类,int是java的一种基本数据类型(byte,char,short,int,long,float,double,boolean)

        Integer是对象的引用,默认值为null,实例化后是一个对象的引用,指向存放该对象的地址,int作为基本数据类型,默认值为0

    
    
  • 相关阅读:
    NIO中几个非常重要的技术点
    NIO的epoll空轮询bug
    mysql支持跨表删除多条记录
    使用Fastjson生成Json字符串少字段属性(数据丢失)
    Linux系统下安装rz/sz命令及使用说明
    Slave_SQL_Running: No mysql同步故障
    二次幂权限设计
    spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件)
    XStream别名;元素转属性;去除集合属性(剥皮);忽略不需要元素
    JDBC通用DAO
  • 原文地址:https://www.cnblogs.com/ashleyboy/p/9043674.html
Copyright © 2011-2022 走看看