天天看点

java 拆箱_Java自动装箱拆箱

一、装箱、拆箱定义

如果一个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...。

四、存储的位置

因为是对象,所以存储在堆中。