【转】Java自动装箱、拆箱、缓冲池

时间:2023-12-13 19:41:44

JDK5以后

Integer a = 3;              这是自动装箱
int     i = new Integer(2); 这是自动拆箱
就是基本类型和其对应的包装类型在需要的时候可以互相转换,具体过程由编译器完成
比如自动装箱:
Integer a=3;
其实编译器调用的是static Integer valueOf(int i)这个方法
查阅JDK知道,
valueOf(int i)返回一个表示指定的int 值的Integer 对象
那么就变成这样: Integer a=3;   =>    Integer a=Integer.valueOf(3);
对应的  int intValue()  返回该Integer对象的int值,是拆箱

我们再来看Integer缓存, 
下面是IntegerCache类的源码
 
Java代码 
private static class IntegerCache   //定义类名 
{   
    static final int high;   
    static final Integer cache[];   //cache缓存是一个存放Integer类型的数组 
 
    static  //初始化 
    {   
        final int low = -128;       //最小值是固定的 
        int h = 127;                //最大值暂时是127 
        if (integerCacheHighPropValue != null) //这段if代码不用深究,是一些判断,我看得眼花啊 
        {   
            int i = Long.decode(integerCacheHighPropValue).intValue();   
            i     = Math.max(i, 127);   
            h     = Math.min(i, Integer.MAX_VALUE - -low);   
        }   
        high = h;  //此时high就是127  
 
        cache = new Integer[(high - low) + 1];  //有256个元素 
        int j = low;                            //j的初始值是-128 
        for(int k = 0; k < cache.length; k++)   //缓存区间数据    
            cache[k] = new Integer(j++);        //将-128~127包装成256个对象存入缓存 
    }   
    private IntegerCache(){}  //构造方法,不需要构造什么 

 
 
再来看valueOf方法
 
Java代码 
public static Integer valueOf(int i)  
{   
    if(i >= -128 && i <= IntegerCache.high) 
    { 
        //如果i在-128~127之间,就直接在缓存中取出i的Integer类型对象 
        return IntegerCache.cache[i + 128];   
    }     
    else 
    { 
        return new Integer(i);  //否则就在堆内存中创建 
    }     
}  
 
 
valueOf方法会自动调用IntegerCache这个类,
IntegerCache初始化后内存中就有Integer缓冲池cache[]了,
-128~127区间的int值有其对应的的包装对象
java使用该机制是为了达到最小化数据输入和输出的目的,这是一种优化措施,提高效率
其他的包装器:
Boolean:(全部缓存)
Byte:    (全部缓存)
 
 
Character (   <=127 缓存)
Short     (-128~127 缓存)
Long      (-128~127 缓存)
 
 
Float     (没有缓存)
Doulbe    (没有缓存)

主题:java迷题:等于,还是不等于?
 
代码片段1
 
public static void main(final String[] args) {  
 
    Integer a = new Integer(100);  
 
    Integer b = 100;  
 
    System.out.println(a == b);   
 
}
 
解答:
 
结果输出false
 
因为new Integer(100)是指明了再堆内存中创建对象
 
而Integer b = 100; 这句是自动装箱,
 
得到的是Integer缓冲池中的对象,是这句代码return IntegerCache.cache[100 + 128]
 
明显a和b的地址是不一样的,不是同一个对象
 
 
 
代码片段2
 
public static void main(final String[] args) {  
 
    Integer a = 100;  
 
    Integer b = 100;  
 
    System.out.println(a == b);   
 
}
 
解答:
 
结果输出true
 
a和b指向了同一个对象,都是IntegerCache.cache[100 + 128]
 
 
 
代码片段3
 
public static void main(final String[] args) {  
 
    Integer a = 156;  
 
    Integer b = 156;  
 
    System.out.println(a == b);   
 
}
 
解答:
 
结果输出false
 
由于156大于128,它的包装对象不在缓冲池中,而是执行return new Integer(156);
 
new了2次,都在堆内存中,但地址不一样
 
 
 
代码片段4
 
public static void main(final String[] args) {  
 
    Integer a = Integer.valueOf(100);  
 
    Integer b = 100;  
 
    System.out.println(a == b);   
 
}
 
解答:
 
结果输出true
 
我们上面说过了,Integer b = 100 就相当于Integer b=Integer.valueOf(100)
 
所以a和b指向缓冲池中的同一对象