今天我们看一下,享元模式在Java Integer String中的应用,

享元模式在Java中的int包装类 Integer中,也有所体现,比如如下的代码

Integer i1 = 56;

Integer i2 = 56;

Integer i3 = 129;

Integer i4 = 129;

System.out.println(i1 == i2);

System.out.println(i3 == i4);

返回一个true,一个false

为什么呢?

是因为其底层有了Integer的享元模式对象池,IntegerCache类,如果创建的对象在-128到127之间,会直接从IntegerCache中返回,如果不在Cache中,才会调用new的方法去创建

public static Integer valueOf(int i) {

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

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

return new Integer(i);

}

这就是享元模式下的Integer对象池

具体的JDK源码如下

/**

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

}

在IntegerCache的代码实现中,可以看出,会在加载类的时候,直接创建从-128到127的对象池,然后在后续的使用中,直接取出即可

而且提供了设置最大缓存值的方式,可以去调整最大缓存值

//方法一:

-Djava.lang.Integer.IntegerCache.high=255

//方法二:

-XX:AutoBoxCacheMax=255

除此外,Long Short Byte,都利用了享元模式来缓存数据,比如Long类型的LongCache享元工厂类

在String中,也有着享元模式

比如,如下的代码

String s1 = “小争哥”;

String s2 = “小争哥”;

String s3 = new String(“小争哥”);

System.out.println(s1 == s2);

System.out.println(s1 == s3);

上面是一个true,一个false

String也会开辟一段的存储区来存储字符串常量,这个存储区就是字符串常量池,

实际上,享元模式对于JVM的垃圾回收并不好,应为享元的工厂类中保存了享元对象的引用,导致了享元对象在没有任何使用的时候,也不容易被回收,所以使用享元模式,需要去验证,使用享元模式是否可以真正的节省内存,不然就不要过度的使用这个模式

发表评论

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