看完编译器替我们做的,接下来我们再通过源码看看,首先是自动装箱 valueOf() 方法:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }我们可以看到,首先是if方法, 对传入的int 数值进行判断,如果 i >= -128 且i <= 127 那么就会从IntegerCache缓存中获取指定数字的封装类,如果不存在则 new 出一个新的封装类,关于 IntegerCache ,其内部实现了一个Integer的静态常量数组,在类加载的时候,执行static静态块进行初始化-128~127之间的Integer对象,存放到cache数组中,cache属于常量,存放在java的方法区中,对方法区不太了解的小伙伴可以先留空,后面我会单独水一篇的~
额外补充一下:上边我们只看了Integer封装类的自动装箱方法,从方法中我们了解了在-128~127之间使用了缓存,那么是不是意味着别的封装类也是这样呢?其实不是的,首先Integer使用缓存原因是该区间会被经常使用到,且数量个数比较确定,就256个值,所以为了提高效率,防止每次自动装箱都创建一次对象实例,然后就你懂得~,而double、float浮点型是没有使用缓存的,因为小数点的原因,所以在这个区间范围内个数是比较泛的,即不适合缓存,没有意义。
我们通过一段代码看看这个缓存的效果吧:
public class Test2 { public static void main(String[] args) { Integer a = 100; Integer b = 100; Integer c = 200; Integer d = 200; System.out.println(a==b); // 打印true System.out.println(a==b); // 打印false } }接着再来看自动拆箱 intValue() 方法:
private final int value; public int intValue() { return value; }这个方法就比较简单了,调用时直接返回了基本数据类型的 value 值。
至此我们看完了自动装箱、自动拆箱,以Integer为例我们知道了使用 valueOf() 方法实现装箱,使用 intValue() 方法实现拆箱,接下来我们再结合几行代码重新回顾一下:
1. Integer a = new Integer(100); 2. Integer b = 100; 3. b+=100;
第一行代码:new 了一个 Integer 对象实例,将 int 类型的数据传入包装成了 Integer 类型。
第二行代码:首先我们知道 100 是 int 类型的,但是等待复制的 b 是 Integer 类型,此时就用到了自动装箱,b = Integer.valueOf(100),将100包装成包装类了「通过反编译验证」
第三行代码:用到了自动装箱+自动拆箱,b = b + 100 = Integer.intValye(b) + 100 此时计算结果得到的应该是 int 类型的 b,但是 b 又被限定了是 Integer 类型,所以就又要用到 Integet.valueOf() 自动装箱。
4、 上才艺才艺一:如何理解Java中的自动拆箱和自动装箱?
答:自动装箱就是将基本数据类型自动转换为封装类型,自动拆箱是将封装类型自动转换为基本数据类型。
才艺二:能说一下是通过哪些方法实现自动拆箱、装箱的吗?
答:以Integer为例,使用Integer.valueOf()方法实现装箱,使用Integer.intValue()方法实现拆箱。