将程序视点设为星标精品文章第一时间阅读
大家好,欢迎来到程序视点
!我是小二哥。
上一篇文章中,我们分享包装类的缓存机制时,提到了自动装箱的问题。今天我们就重点分享自动装箱的原理
,及其相关的知识点(笔试必考)!
前面介绍过,把基本类型转换成包装类型的过程叫做装箱(boxing)。反过来,把包装类型转换成基本类型的过程叫做拆箱(unboxing)。
我们来举个例子:
代码语言:javascript复制Integer i = 10; //装箱
int n = i; //拆箱
上面两行代码,就执行了自动装箱和自动拆箱的过程。有小伙伴可能就说了,“你说装箱就是装,拆箱就是拆呀?怎么证明呢?”
最好的证明,就是看系统运行时真正执行了什么?我把上面它们执行的字节码粘贴下:
大家只需看字节码片段中,红框的内容就好。几个简单的单词,大家应该都熟悉。invoke static java/lang/Integer.valueOf (I)
:调用静态方法。哪个静态方法呢?Java的lang包下Integer类的静态方法,方法名是valueOf(I)
,其中I
就是传入的参数。那么,执行第一句代码的时候,系统为我们执行了:
Integer i = Integer.valueOf(10);
同理,执行第二句代码的时候,系统为我们执行了:
代码语言:javascript复制int n = i.intValue();
也就是说,自动装箱是通过 Integer.valueOf()
完成的;自动拆箱是通过 Integer.intValue()
完成的。
必考点
理解了原理之后,我们来看看常考的知识点。
基本类型和包装类型进行 == 比较,包装类型会自动拆箱,直接和基本类型比较值
代码语言:javascript复制int a = 9;
Integer b = 9;
System.out.println(a == b);
由于包装类型会自动拆箱后再比较,上述代码的结果为 true。
自动装箱时的缓存机制
当需要进行自动装箱时,如果数字在 -128 至 127 之间,会直接使用缓存中的对象,而不是重新创建一个对象。Integer 缓存源码:
代码语言:javascript复制public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i (-IntegerCache.low)];
return new Integer(i);
}
主要是这个IntegerCache.cache
数组中缓存着的。大家可以翻阅上一篇文章
举个例子:
代码语言:javascript复制Integer a = 100;
Integer b = 100;
System.out.println(a == b);
这里的答案是:true
。
Integer a = 199;
Integer b = 199;
System.out.println(a == b);
而这时的答案是:false
。因为 199 不在 -128 至 127 范围之内,所以 new 出来了两个 Integer 对象。既然是new出来的,那就会在堆空间中产生不同的对象,不同的对象在进行 ==
比较的时候,比较的是内存中的地址
,不同对象的内存地址肯定不一样,所以返回false。
自动拆装箱的高阶考点
直接来看题:
代码语言:javascript复制Integer a = 9999;
Integer b = 9999;
System.out.println(a 1 == b 1);
先别看下面的答案,看你能做对不?
这2个包装类型的Integer在运算时会自动拆箱,变成2个基本数据类型的比较,相当于在判断:
代码语言:javascript复制a.intValue() 1 == b.intValue() 1
而两个基本数据类型比较时只看数值大小,故结果为true。
好啦!今天的内容就到这里啦!希望以后面试到自动拆装箱的比较问题,大家都能手到擒来~