一、装箱、拆箱定义
如果一个int型量被传递到需要一个Integer对象的地方,那么,编译器将在幕后插入一个对Integer构造方法的调用,这就叫做自动装箱。而如果一个Integer对象被放到需要int型量的地方,则编译器将幕后插入一个队intValue方法的调用,这就叫做自动拆箱。
public static voidmain(String[] args) {//装箱
Integer i1 = Integer.valueOf(1);//自动装箱
Integer i2 = 1;//默认执行valueOf(1);
System.out.println(i1 == i2);//true
//自动拆箱
int i3 =i1.intValue();int i4 =i2.intValue();
System.out.println(i3== i4);//true
//超出Integer的缓存范围,不从私有静态内部类IntegerCache的数组cache中获得,通过new返回新对象
Integer i5 = 128;
Integer i6= -129;
Integer i5_1= 128;
Integer i6_1= -129;
System.out.println(i5== i5_1);//false
System.out.println(i6 == i6_1);//false
}
所以说,对于-127~127之间的值,Integer对象中存在一个IntegerCache的私有静态内部类,这个内部类有一个Integer类型的静态常量数组,在这个内部类中通过静态方法块,初始化了这个静态常量数组。默认这个数组保存[-127,128)之间的Integer对象。源码如下:
1 private static classIntegerCache {2 static final int low = -128;3 static final inthigh;4 static finalInteger cache[];5
6 static{7 //high value may be configured by property
8 int h = 127;9 String integerCacheHighPropValue =
10 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");11 if (integerCacheHighPropValue != null) {12 try{13 int i =parseInt(integerCacheHighPropValue);14 i = Math.max(i, 127);15 //Maximum array size is Integer.MAX_VALUE
16 h = Math.min(i, Integer.MAX_VALUE - (-low) -1);17 } catch( NumberFormatException nfe) {18 //If the property cannot be parsed into an int, ignore it.
19 }20 }21 high =h;22
23 cache = new Integer[(high - low) + 1];24 int j =low;25 for(int k = 0; k < cache.length; k++)26 cache[k] = new Integer(j++);27
28 //range [-128, 127] must be interned (JLS7 5.1.7)
29 assert IntegerCache.high >= 127;30 }31
32 privateIntegerCache() {}33 }
通过下面的源码可以知道,为什么Integer i = 128;与Integer y = 128;,通过==比较的结果为false。如果要赋值的int变量在范围内,则返回数组中的对象给Integer,如果不在,则通过带参构造方法,new一个新的Integer对象。
1 public static Integer valueOf(inti) {2 if (i >= IntegerCache.low && i <=IntegerCache.high)3 return IntegerCache.cache[i + (-IntegerCache.low)];4 return newInteger(i);5 }
二、其它包装类型
The Java Language Specification, 3rd Edition 写道:
为了节省内存,对于下列包装对象的两个实例,当它们的基本值相同时,他们总是==:
Boolean :全部缓存
Byte :全部缓存
Character : <=127缓存
Short : (-128,127)缓存
Long : (-128,127)缓存
Float : (没有缓存)
Double : (没有缓存)
其中Character的缓存源码:
1 private static classCharacterCache {2 privateCharacterCache(){}3
4 static final Character cache[] = new Character[127 + 1];5
6 static{7 for (int i = 0; i < cache.length; i++)8 cache[i] = new Character((char)i);9 }10 }
其中Float没有缓存,直接返回源码:
1 public static Float valueOf(String s) throwsNumberFormatException {2 return newFloat(parseFloat(s));3 }
三、用处
除了包装类提供了额外的方法外,当使用集合框架时,泛型为Object类型,所以如果声明为List list...,则这样是不行的,必须声明为List list...。
四、存储的位置
因为是对象,所以存储在堆中。