一.integer包装类
先看个小例子
Integer i1 = 25;
Integer i2 = 25;
Integer i21 = Integer.valueOf(25);
Integer i22 = new Integer(25);
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i1 == i2); //true
System.out.println(i1 == i21); //true
System.out.println(i1 == i22); //false
System.out.println(i3 == i4); //false
看到结果,why?我们知道==比较是否指向相同的对象,本质是栈内局部变量表中reference存储的值是否相等,对于基本类型存储的是数据值,对于引用类型(接口,类,数组)存储的是堆中对象的地址。
1.Integer i22 = new Integer(25); 毫无疑问是在堆中创建一个新对象;
2.Integer i1 = 25;我们知道会触发自动装箱操作,也就是调用valueOf()来创建Integer 对象,为何相同呢?因为在类加载时内部类IntegerCache中的静态块已经把部分(默认是-128~127)Integer对象初始化好缓存起来了static final Integer cache[];
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"); --可配置
...
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
so,Integer i1 = 25; 和 Integer.valueOf(25);直接来这个cache[]读取共享复用就行了。
- Integer i3 = 128; Integer i4 = 128; 超出了high位,需要自行创建新对象。
二. String享元模式和包装类型区别
Integer 类中要共享的对象,是在类加载的时候,就集中一次性创建好的。
但是,对于字符串来说,我们没法事先知道要共享哪些字符串常量,所以没办法事先创建好,只能在某个字符串常量第一次被用到的时候,存储到常量池中,当之后再用到的时候,直接引用常量池中已经存在的即可,就不需要再重新创建了。