深入浅析Java中拆箱与自动装箱的原理

  介绍

这篇文章给大家介绍深入浅析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中拆箱与自动装箱的原理