看了Java的自动装箱与拆箱,感觉很疑惑,就看了不少博客,还是没咋理解,就看了源码,发现了规律。就写篇博客记下来,好回顾。因为整型int比较典型,就拿Integer举例说明。
//创建一个Integer类,并赋值。
Integer in = 10;
//自动装箱函数
public static Integer valueOf(int i) {
//判断整型数值是否存在与之对应的包装类,如果存在就不用再创建了,否则就new一个
if (i >= IntegerCache.low && i <= IntegerCache.high) {
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// 高值可以通过属性配置
int h = 127;
//这些代码我的理解就是整型包装类数组可以自己设置的h
// String integerCacheHighPropValue =
// VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
// if (integerCacheHighPropValue != null) {
// try {
// h = Math.max(parseInt(integerCacheHighPropValue), 127);
// // 最大数组大小为 integer.max 值
// h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
// } catch( NumberFormatException nfe) {
// //如果属性不能解析为 int 类型,忽略它。
// }
// }
high = h;
// 如果可能的话,从存档中加载 integercache.archivedcache
// VM.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
//如果只看没注释的代码,则将创建-127到128的整型包装类数组
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// 范围[-128,127]必须实行(jls75.1.7)
// assert IntegerCache.high >= 127;
}
也就是说当我声明一个Integer类时,位于类里面的static代码块就执行了,就帮我创建了一个存放整型包装类的数组cache,数组下标从0开始,里面存放的是属性值int为-128的整形包装类的地址,到size结束,里面存放的是属性值int为127的整形包装类的地址,所以Integer in = 10, 自动装箱,相当于调用了Integer.valueOf(10)方法。 首先判断in值是否在-128和127之间,如果在-128和127之间则直接从IntegerCache.cache整型包装类数组中获取指定数字的包装类;不存在则new出一个新的包装类。
做个测试:
package Pop;
public class textInt {
public static void main(String[] args) {
Integer in1 = 10;
Integer in2 = 10;
Integer in3 = 1000;
Integer in4 = 1000;
System.out.println(in1==in2);
System.out.println(in3==in4);
}
}
结果如下:
true
false
总结:在判断都是装箱包装类的数值是否相等时,一定要小心,因为包装类包装的数值如果不在IntegerCache.cache数组里,就会new,但是new的地址不一样。所以比较时最好与一个基本数据类型,这样包装类就会自动拆箱,实际比较的是它的属性值。