Java基础 | 16.自动装箱与拆箱、包装类的缓存池

参考文章

详细解析包装类及其缓存池,不会还有人不知道吧?

前言

为方便描述,本文中所有的包装类、缓存池,都以Integer类举例。

注意:Float和Double没有缓存池

1.初探包装类的缓存池

1.1.什么是缓存池

Integer缓存池在创建时,将值∈[-128, 127]的Integer对象预先存储在一个变量名为cache的Integer数组中。每当程序调用Integer.valueOf( int )来获取Integer对象时,会判断int的值是否在[-128, 127]:

  • 在,将引用指向cache中的缓存对象;
  • 不在,创建新的对象(开辟新的内存空间)并将引用指向该对象,本质上是 new Integer( int )

1.2.什么时候会创建缓存池

Integer类被加载时创建缓存池

Integer缓存池(Integer的静态内部类)的源码如下:

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];
    static {
        int h = 127;
        String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
            }
        }
        high = h;
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
        assert IntegerCache.high >= 127;
    }
    private IntegerCache() {}
}

在Integer类被加载时,静态成员就会被加载。而IntegerCache是Integer类的静态内部类,因此Integer类被加载时,就会创建缓存池。

2.自动装箱与拆箱

// 装箱:Integer.valueOf(int)
Integer boxingI = 100;

// 拆箱:int.intValue();
int i = boxingI;

2.1.自动装箱

自动将基本数据类型转换成包装数据类型。下方两段代码在运行时是等价的:

// 触发自动装箱
Integer boxingI = 100;
// 手动装箱
Integer boxingI = Integer.valueOf(100);

换言之,当程序执行到Integer packI = 100;时,实际上程序调用了包装类的static valueOf( int )

public static Integer valueOf(int i) {
    // 如果数值在缓存池范围内,从缓存池获取对象
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    // 如果不在范围内,new一个新的对象并返回
    return new Integer(i);
}
  • 若数值在缓存池范围内,从缓存池中获取对象(不会创建新对象);
  • 若数值不在缓存池范围内,创建一个新的Integer对象。

2.2.拆箱

将包装数据类型变成基本数据类型(注意:这里不涉及向上转型和向下转型,因为int不是类

Integer boxingI = 100;
// 拆箱
int i = boxingI;
Integer boxingI = 100;
// 拆箱
int i = boxingI.intValue();

intValue( )是非静态的成员方法,而intValue( )的源码非常简单:

public int intValue() {
    return value;
}

3.Integer.valueOf( int )和new Integer( int )

Integer.valueOf( int )的源码得知,当传入的int不在缓存池范围内,就会**new Integer( **int )

  • 若在缓存池范围内,从缓存池获取对象。
  • 若不在缓存池范围内,创建新的对象。
Integer i1 = Integer.valueOf(100);
Integer i2 = Integer.valueOf(100);
Integer i3 = new Integer(100);

System.out.println(i1 == i2);	// true - 都是缓存池中的同一个对象
System.out.println(i1 == i3);	// false - i1是缓存池中的对象,i3是新建的对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值