包装类的缓存机制与valueOf()


title: 包装类的缓存机制
date: 2019-02-28 21:50:12
tags: Java基础


包装类的缓存机制与valueOf()

引言

Java有8种基本类型,每种都有一个包装类型,有很多静态方法、变量等,方便对数据进行操作。包装类可以由valueOf()静态方法去创建,也可以用new关键字去创建实例对象,但为什么推荐使用valueOf()来创建呢。


首先,我们来看一个例子:

public class Test {

public static void main(String[] args) {
    Integer a = 1;

    Integer b = 1;

    Integer c = 128;

    Integer d = 128;

    if(a == b){

        System.out.println("a与b相同");

    }
    if(c == d){

        System.out.println("c与d相同");

    }
}

}

运行结果

a与b相同 c与d不相同

分析

这段代码创建了4个Integer类型的对象实例a、b、c、d,照常理来说,4个对象,其引用地址不同,此例子的输出应该都为不相同,但结果确是a与b相同,c与d不同,这是为什么?

此处我们是采用自动装箱的方式来创建的Integer对象,而这相当于调用了valueOf()的方法,所以就得从valueOf()这个静态方法说起。

###valueof的分析

首先,看看IntegervalueOf()方法的源码

public static Integer valueOf(int i) {

            if (i >= IntegerCache.low && i <= IntegerCache.high)

                return IntegerCache.cache[i + (-IntegerCache.low)];

            return new Integer(i);

        }

分析

此段代码中如果不满足i>=IntegerCache.low && i<= IntegerCache.high这个表达式,就通过new来得到对象,如果满足呢?

再来看看IntegerCache类,IntegCache类是Integer类的一个内部静态类,其源码如下。

  /**

 * Cache to support the object identity semantics of autoboxing for values between

 * -128 and 127 (inclusive) as required by JLS.

 *

 * The cache is initialized on first usage.  The size of the cache

 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.

 * During VM initialization, java.lang.Integer.IntegerCache.high property

 * may be set and saved in the private system properties in the

 * sun.misc.VM class.

 */ 

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;

                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() {}

        }

分析

首先,从Javadoc中看出这个类是用来实现缓存的。它定义了三个静态参数,缓存数组cache,数组最小值low,赋值为-128以及数组最大值high,最大值映射到了"java.lang.Integer.IntegerCache.high"上。

,并支持 -128 到 127 之间的自动装箱过程。最大值 127 可以通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改。

修改jvm参数后

添加jvm参数

运行结果

a与b相同 c与d不相同

结论

IntegerCache这个Integer私有静态类代表Integer缓存,它在被首次主动使用时,会被初始化,static代码块中的会被执行,通过一个 for 循环创建出一个值为-128~127的一个缓存数组cache,以后,如果创建的值在lowhigh之间,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。这种机制使我们可以根据应用程序的实际情况灵活地调整来提高性能。是什么原因选择这个 -128 到 127 这个范围呢?因为这个范围的整数值是使用最广泛的,通过使用共享对象,就可以节省内存空间了。在程序中第一次使用 Integer 的时候也需要一定的额外时间来初始化这个缓存。这种机制在其他包装类中也有类似的实现。这种缓存策略也是一种设计模式,叫做享元模式。

猜你喜欢

转载自blog.csdn.net/weixin_38950807/article/details/88046255
今日推荐