Integer的自动装箱和自动拆箱
装箱:基本类型 --> 包装类/引用类型
Integer i1=100; 在编译后,class文件中自动加上了valueOf方法
拆箱:包装类/引用类型 --> 基本类型
int i2 = i1; 在编译后,class文件中自动加上了intValue方法
注意:自动装箱和自动拆箱只发生在编译阶段。
Integer.valueOf方法
public static Integer valueOf(int i) {
//判断是否在Integer内部的缓存数组中,如果存在则直接返回缓存数组中的对象
//IntegerCache是Integer的内部类
if (i >= IntegerCache.low && i <= IntegerCache.high)
//根据索引获取缓存中的Integer
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
IntegerCache类
private static class IntegerCache {
static final int low = -128; //缓存池中最小值,-128
static final int high; //缓存中最大值,默认为127
static final Integer cache[];
static {
// 最大值默认为127
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;
//开辟大小为(high - low) + 1的Integer数组
cache = new Integer[(high - low) + 1];
int j = low;
//IntegerCache类初始化的时候就对内部的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;
}
private IntegerCache() {}
}
注:数组赋值的另外写法
int ii[];
ii = new int[5];
System.out.println(Arrays.toString(ii)); //[0, 0, 0, 0, 0]
代码示例
Integer i1 = 100;
Integer i2 = 100;
System.out.println(i1==i2); //true 因为取出来的都是缓存池中的Integer对象,所以对象地址相同
Integer i3 = 1000;
Integer i4 = 1000;
System.out.println(i3==i4); //false 超出了缓存池,新创建对象
System.out.println(i3.equals(i4)); //true 比较值,相等
结论
创建Integer的时候,以下两种方法:
方法1:Integer n = new Integer(100); //总是创建新的对象
方法2:Integer n = Integer.valueOf(100); //静态工厂方法,尽可能地返回缓存的实例以节省内存
所以,为了节省内存,Integer.valueOf()对于较小的数,始终返回相同的实例,因此,有时候使用 == 比较“恰好”为true,但我们绝不能因为Java标准库的Integer内部有缓存优化就用 == 比较,必须用equals()方法比较两个Integer