Java自动装箱缓存机制

尝试运行这段代码:

相似的两段代码,得到的结果却完全不相同。

首先要知道在java中==比较的是对象的引用,从直觉出发,无论是integer1、integer2还是integer3、integer4都是不同的引用,结果都应该是不等的。

造成这个结果的原因是JDK1.5引入的包装类自动装箱时的缓存机制

自动装箱的概念:

Integer a = 10; //自动装箱,相当于下面这句
Integer a = Integer.valueOf(10);

而看看Integer中valueOf(int)的源码:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];//这句就是我们要研究的重点
    return new Integer(i);
}

IntegerCache是一个缓存类,它的内部有一个静态的Integer cache[]数组,在这个类第一次被加载时,会用整数值在-128~127之间的Integer实例对象填充这个数组,如果调用valueOf方法的时候参数值在这个范围内,就会从IntegerCache中的cache数组去取出这样一个共享对象。

这样就能回答一开始的程序integer1、integer2为什么相等了,因为他们都是从cache数组中取出来的同一个引用。

而300这个数是不在-128~127之间的,缓存数组中不存在这样的对象,最终是调用了构造方法创建了两个不同的Integer对象。


拓展:IntegerCache的静态代码块

static {
    // 缓存的数据范围可以由用户设置,这里从配置中获取了用户设置的缓存范围
    int h = 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);
            // 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;

    // 这里循环构造Integer对象填充cache数组
    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;
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/java%e8%87%aa%e5%8a%a8%e8%a3%85%e7%ae%b1%e7%bc%93%e5%ad%98%e6%9c%ba%e5%88%b6/

发表评论

电子邮件地址不会被公开。