• Integer缓存机制-基本数据类型和包装类型-自动拆装箱


    Integer缓存机制

    总结:

    1、jdk1.5对Integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,所以只要在缓存范围内值相等自动装箱返回的对象一样。jdk1.6后缓存范围的最大值127可以通过设置jvm的启动参数(-XX:AutoBoxCacheMax=size)调整
    2、Integer的缓存只在自动装箱时有效,使用构造器(new)创建的对象不会触发缓存
    3、int和Integer比较时不用考虑缓存问题,因为Integer会自动拆箱为int再和int比较,这时只是单纯的比较值是否相等

    详解:
    针对Integer常见的一个面试题为

    Integer i1 = 100;
    Integer i2 = 100;
    Integer j1 = 200;
    Integer j2 = 200;
    System.out.println(i1 == i2); // 输出 true
    System.out.println(j1 == j2); // 输出 false

    我们对于Integer最基本的理解是Integer是int的包装类,是引用数据类型,引用数据类型用==比较的是对象的内存地址。
    我们来看i1的创建过程(jdk1.8)
    首先会对Integer i1 = 100;自动装箱(其实就是调用valueOf方法),java会把这段编译为Integer i1 = Integer.valueOf(100),可以自行查看class文件验证。
    然后再看Integer.valueOf方法:

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

    可以清楚的看到是先从IntegerCache取值,IntegerCache.low IntegerCache.high 范围外则直接new对象(new的对象会存在堆内存中)

    我们再来看IntegerCache类,IntegerCache为Integer的私有静态类

     1 /**
     2      * Cache to support the object identity semantics of autoboxing for values between
     3      * -128 and 127 (inclusive) as required by JLS.
     4      *
     5      * The cache is initialized on first usage.  The size of the cache 第一次使用时生效
     6      * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. 可通过参数设置最大值
     7      * During VM initialization, java.lang.Integer.IntegerCache.high property
     8      * may be set and saved in the private system properties in the
     9      * sun.misc.VM class.
    10      */
    11 
    12     private static class IntegerCache {
    13         static final int low = -128;
    14         static final int high;
    15         static final Integer cache[];
    16 
    17         static {
    18             // high value may be configured by property
    19             int h = 127;
    20             String integerCacheHighPropValue =
    21                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    22             if (integerCacheHighPropValue != null) {
    23                 try {
    24                     int i = parseInt(integerCacheHighPropValue);
    25                     i = Math.max(i, 127);
    26                     // Maximum array size is Integer.MAX_VALUE
    27                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
    28                 } catch( NumberFormatException nfe) {
    29                     // If the property cannot be parsed into an int, ignore it.
    30                 }
    31             }
    32             high = h;
    33 
    34             cache = new Integer[(high - low) + 1];
    35             int j = low;
    36             for(int k = 0; k < cache.length; k++)
    37                 cache[k] = new Integer(j++);
    38 
    39             // range [-128, 127] must be interned (JLS7 5.1.7)
    40             assert IntegerCache.high >= 127;
    41         }
    42 
    43         private IntegerCache() {}
    44     }

    Integer的缓存通过for循环创建存放到一个数组中,注释已经解释该数组会在Integer第一次使用时初始化,结合类加载顺序来理解,第一次使用Integer时内部静态类会被初始化,静态代码块会被执行,存到堆中。会有第一次惩罚

    jdk1.5源码参考

     1 private static class IntegerCache {
     2         static final Integer[] cache = new Integer[256];
     3 
     4         static {
     5             for (int i = 0; i < cache.length; i++) {
     6                 cache[i] = new Integer(i - 128);
     7             }
     8         }
     9     }
    10 
    11     public static Integer valueOf(int paramInt) {
    12         if ((paramInt >= -128) && (paramInt <= 127)) {
    13             return IntegerCache.cache[(paramInt + 128)];
    14         }
    15         return new Integer(paramInt);
    16     }

    Integer与int用==比较时Integer会自动拆箱(调用intValue()方法)为int进行比较
    i1 == 100 会编译成 i1.intValue() == 100


    其他缓存的对象
    这种缓存行为不仅适用于Integer对象。我们针对所有整数类型的类都有类似的缓存机制。
    有 ByteCache 用于缓存 Byte 对象
    有 ShortCache 用于缓存 Short 对象
    有 LongCache 用于缓存 Long 对象
    有 CharacterCache 用于缓存 Character 对象
    Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 可以通过参数改变范围外,其它的都不行。

    参考博文:https://blog.csdn.net/qq_27093465/article/details/52473649

    int与Integer(基本类型与包装类型)

    Integer是int的包装类型,两者的区别为:

    1、int初始值为0,Integer初始值为null,所有的引用类型都为null;

    2、Integer为引用类型,对象存放在堆中。int为基本数据类型,对象存放在栈中;

    使用包装类的好处:

    1、Integer封装了很多处理方法,方便操作,比如进制转化(toBinaryString)、数据类型之间的转化(toString);

    2、解决有些类型不支持基础数据类型的情况,比如List只能接收引用类型;

    至于何时使用基本数据类型,何时使用包装类型这个就要看具体需求,当只是作为数值不需要更多的操作时用基本类型就可,灵活使用

    基本数据类型和对应的包装类
    int——Integer
    float——Float 
    double——Double 
    byte——Byte
    long——Long
    char——Character
    boolean——Boolean
    short——Short

    自动拆装箱(jdk1.5引入)

    自动拆箱实际上就是引用类型自动转化成基本数据类型,自动装箱实际上就是基本数据类型自动转化成对应的引用类型

    比如创建Integer i = new Integer(100); 可以直接写成Integer i = 100;不需要强转  (自动装箱)

    int j = i  基本数据类型j可以直接等于引用类型i  (自动拆箱)

    1 Integer i = 1;
    2 int j = i;
    3 
    4 /**
    5 *    上面代码编译成class后
    6 */
    7 Integer i = Integer.valueOf(1);
    8 int j = i.intValue();    

    由上可以看出自动装箱实际上就是调用了valueOf方法,自动拆箱调用了intValue方法

     

  • 相关阅读:
    Linux的安装(虚拟机环境)与基础配置
    爬虫之proxy(代理)
    爬虫之UserAgent
    爬虫之urllib.error模块
    【React自制全家桶】五、React组件的生命周期函数详解
    【React自制全家桶】四、React中state与props的分析与比较
    【React自制全家桶】三、React使用ref操作DOM与setState遇到的问题
    【React自制全家桶】二、分析React的虚拟DOM和Diff算法
    小程序API:wx.showActionSheet 将 itemList动态赋值
    解决json_encode中文乱码问题
  • 原文地址:https://www.cnblogs.com/zh-ch/p/9838142.html
Copyright © 2020-2023  润新知