这篇文章给大家介绍深入浅析Java中拆箱与自动装箱的原理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
<强>什么是自动装箱和拆箱强>
自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成整数对象,这个过程叫做装箱,反之将整数对象转换成int类型值,这个过程叫做拆箱,因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型字节,短,char, int,长而浮动,双和布尔对应的封装类为字节,短,字符,整数,长而浮动,翻倍,布尔。
下面例子是自动装箱和拆箱带来的疑惑
{公共类测试 公共静态void main (String [] args) { 测试(); } 公共静态空白测试(){ int i=40; int i0=40; 整数i1=40; 整数i2=40; 整数i3=0; 整数预告=new整数(40); 整数i5=new整数(40); 整数16=new整数(0); 双d1=1.0; 双d2=1.0; System.out.println(“我=i0 \ t"我==i0) + (); System.out.println (“i1和i2 \ t"=;+ (i1和i2)==); System.out.println (“i1和i2 +=i3 \ t"+ (i1和i2 + i3)==); System.out.println(“预告=i5 \ t"+(预告==i5)); System.out.println(“当=i5 + 16 \ t"+(预告==i5 + 16)); System.out.println (“d1=d2 \ t"+ (d1==d2)); System.out.println (); } }
请看下面的输出结果跟你预期的一样吗?
输出的结果:
我=i0 ,# 8194;真正的
i1和i2,=# 8194;真正的
i1和i2 +=i3, # 8194;及# 8194;真正的
预告=i5和# 8194;假
预告=i5 + 16, # 8194;及# 8194;真
d1=d2假
为什么会这样?带着疑问继续往下看。
<>强自动装箱和拆箱的原理强>
自动装箱时编译器调用返回对象的值将原始类型值转换成对象,同时自动拆箱时,编译器通过调用类似intValue (), doubleValue()这类的方法将对象转换成原始类型值。
明白自动装箱和拆箱的原理后,我们带着上面的疑问进行分析下整数的自动装箱的实现源码。如下:
公共静态整数返回对象的值(int i) {//判断我是否在-128年和127年之间,如果不在此范围,则从IntegerCache中获取包装类的实例。否则新一个新实例 如果我在=IntegerCache。低,,我& lt;=IntegerCache.high) IntegerCache返回。缓存(i + (-IntegerCache.low)); 返回新的整数(i); }//使用亨元模式,来减少对象的创建(亨元设计模式大家有必要了解一下,我认为是最简单的设计模式,也许大家经常在项目中使用,不知道他的名字而已) 私有静态类IntegerCache { 静态最终int低=-128; 静态最终int高; 最终的静态整数缓存[];//静态方法,类加载的时候进行初始化缓存[],静态变量存放在常量池中 静态{//高价值的可配置属性 int h=127; 字符串integerCacheHighPropValue=https://www.yisu.com/zixun/sun.misc.VM.getSavedProperty (“java.lang.Integer.IntegerCache.high”); 如果(integerCacheHighPropValue !=null) { 尝试{ int i=方法(integerCacheHighPropValue); i=数学。马克斯(我127);//最大数组大小是Integer.MAX_VALUE h=数学。分钟(我,整数。MAX_VALUE -(低)1); }捕捉(NumberFormatException nfe) {//如果属性不能被解析成int,忽略它。 } } 高=h; 缓存=new Integer[(高-低)+ 1]; int j=低; for (int k=0;k=127; } 私人IntegerCache () {} }
整数i1=40;自动装箱,相当于调用了Integer.valueOf(40);方法。
首先判断我值是否在-128年和127年之间,如果在-128年和127年之间则直接从IntegerCache。缓存缓存中获取指定数字的包装类;不存在则新出一个新的包装类。
IntegerCache内部实现了一个整数的静态常量数组,在类加载的时候,执行静态静态块进行初始化-128到127之间的整数对象,存放到缓存数组中.cache属于常量,存放在java的方法区中。
接着看下面是java8种基本类型的自动装箱代码实现。如下:
//布尔原生类型自动装箱成布尔 公共静态布尔返回对象的值(布尔b) { 返回(b, # 63;真:假); }//字节原生类型自动装箱成字节 公共静态字节返回对象的值(字节b) { 最后一个int抵消=128; 返回ByteCache.cache ((int) b +偏移量); }//字节原生类型自动装箱成字节 公共静态短返回对象的值(s) { 最后一个int抵消=128; int sAsInt=s; 如果(sAsInt祝辞=-128,,sAsInt & lt;=127){//必须缓存 ShortCache返回。缓存(sAsInt +偏移量); } 返回新短(s); }//字符原生类型自动装箱成字符 公共静态字符返回对象的值(char c) { 如果(c & lt;=127){//必须缓存 返回CharacterCache.cache [c] (int); } 返回新角色(c); }//int原生类型自动装箱成整数 公共静态整数返回对象的值(int i) { 如果我在=IntegerCache。低,,我& lt;=IntegerCache.high) IntegerCache返回。缓存(i + (-IntegerCache.low)); 返回新的整数(i); }//int原生类型自动装箱成长 公共静态长返回对象的值(l) { 最后一个int抵消=128; 如果(l祝辞=-128,,l & lt;=127){//将缓存 返回LongCache.cache ((int) l +偏移量); } 返回新长(l); }//双原生类型自动装箱成双 公共静态双返回对象的值(双d) { 返回新双(d); }//浮动原生类型自动装箱成浮动 公共静态浮动返回对象的值(浮动){ 返回新的浮动(f); }深入浅析Java中拆箱与自动装箱的原理