Fork me on GitHub

Java自动装箱拆箱

一、装箱、拆箱定义


  如果一个int型量被传递到需要一个Integer对象的地方,那么,编译器将在幕后插入一个对Integer构造方法的调用,这就叫做自动装箱。而如果一个Integer对象被放到需要int型量的地方,则编译器将幕后插入一个队intValue方法的调用,这就叫做自动拆箱。

    public static void main(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 class IntegerCache {
 2         static final int low = -128;
 3         static final int high;
 4         static final Integer 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         private IntegerCache() {}
33     }

  通过下面的源码可以知道,为什么Integer i = 128;与Integer y = 128;,通过==比较的结果为false。如果要赋值的int变量在范围内,则返回数组中的对象给Integer,如果不在,则通过带参构造方法,new一个新的Integer对象。

1     public static Integer valueOf(int i) {
2         if (i >= IntegerCache.low && i <= IntegerCache.high)
3             return IntegerCache.cache[i + (-IntegerCache.low)];
4         return new Integer(i);
5     }

二、其它包装类型


  The Java Language Specification, 3rd Edition 写道:

    为了节省内存,对于下列包装对象的两个实例,当它们的基本值相同时,他们总是==:

  • Boolean :全部缓存
  • Byte :全部缓存
  • Character : <=127缓存
  • Short : (-128,127)缓存
  • Long : (-128,127)缓存
  • Float : (没有缓存)
  • Double : (没有缓存)

其中Character的缓存源码:

 1   private static class CharacterCache {
 2         private CharacterCache(){}
 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) throws NumberFormatException {
2         return new Float(parseFloat(s));
3     }

三、用处


  除了包装类提供了额外的方法外,当使用集合框架时,泛型为Object类型,所以如果声明为List<int> list...,则这样是不行的,必须声明为List<Integer> list...。 

四、存储的位置


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

 

posted @ 2016-07-07 22:58  郑斌blog  阅读(823)  评论(0编辑  收藏  举报