Integer自动拆箱装箱及Integer如何实现常量池源码解析

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

自动拆箱装箱是java经典的语法糖,那么源码是如何实现自动拆箱装箱的呢。下面我们来说明一下。

一、源码如何实现自动拆箱装箱?

1.什么是自动拆箱装箱

在这里插入图片描述
自动装箱是将int数据类型转换成对应的Integer包装类。自动拆箱是将Integer包装类转换成对应的int数据类型。因为是自动进行的,所以在代码中看不到它们具体调用了哪个方法。但是可以通过字节码文件查看自动拆箱装箱是调的是哪个方法。

2.通过字节码确定自动拆箱装箱调了哪个方法

使用javap -verbose +文件名.class查看字节码。
在这里插入图片描述
可以看到,自动装箱调的是Integer.valueof()方法,而自动拆箱调用的是Integer.intValue()方法

3.自动拆箱装箱等价于什么

在这里插入图片描述
自动装箱Integer integer=10等价于Integer integer=Integer.valueof(10)
自动拆箱int integer=new Integer(10)等价于int integer=new Integer(10).intValue();

4.自动拆箱intValue()源码解读

在这里插入图片描述
在这里插入图片描述
可以看到自动装箱的源码非常简单,就是返回成员变量value的值。而value是通过构造方法public Integer(int value)赋值。故 new Integer(10).intValue() 返回的就是构造方法入参10。

二、自动装箱和常量池技术

1.Integer常量池的体现

我们知道常量池就是相同的元素不会在创建第二遍,那既然Integer实现了常量池,它必然也具有该特性。
在这里插入图片描述
在这里插入图片描述
可以看到,当integer赋值为10时,两者的地址值确实相同,但当Integer为1000时,两者的地址值却不同了。由此可见,Integer仅在部分范围内实现了常量池,并没有像string类那样全体字符串都具有常量池特性。

2.解析自动装箱源码Integer.valueof(int i)

上文已经说过自动装箱Integer integer=10等价于Integer integer=Integer.valueof(10)。
而 Integer integer8=10; Integer integer9=10;两个变量地址值相等,是常量池技术的一种体现。
故自动装箱的源码integer.valueof()中实现了常量池技术。下面我们来看下自动装箱源码。

2.1点击进入自动装箱源码

在这里插入图片描述
可以看到当不触发if语句时,即传入int介于范围外时,返回的就是个新建的对象,而每个new新建的对象是在堆内存单独开辟了空间,所以new出的对象之间地址值不可能相等,故Integer integer6=1000;Integer integer7=1000;两者的地址值不同。而当int介于范围内时,返回的是缓存数组中指定的元素,并不新建对象。故 Integer integer8=10; Integer integer9=10;两者地址值相同。

2.2解析自动装箱if模块

可以看到自动装箱的核心模块就是在条件判断中。下面我们对这段代码进行分析。
在这里插入图片描述
在这里插入图片描述
IntegerCache是integer的一个内部类。785行表示静态代码块,在类加载时运行且只运行一次。788行高值映射于jvm启动参数中,通过查看jvm启动参数可知初始高值参数为128。
在这里插入图片描述

793行 i值为128。
795行 h值为128。
802行cache=new Integer[(128+127+1)]=new Integer[256]
803行j=-127。
804行for循环是对缓存数组0到255位每位赋值-127到128。cache[0]=-127,cache[127]=0,cache[255]=128。
也就是说这个静态代码块里的代码,开辟了一个长度256的缓存数组,将-127到128总计256个数字放入了该缓存数组中。由于该缓存数组是static final的,所以它是给所有对象共享且无法改变元素的静态常量。

2.3重新回到valueof方法

在这里插入图片描述
如果i大于等于-127,小于等于128,将从缓存数组中取出对应的元素。例如传入100,那么将取缓存数组中第100+127也就是第227号元素,对应的值是100。而如果不在这个范围内,则直接new integer对象。

总结

自动拆箱调用intValue方法,返回的是用new Integer新建对象时的构造方法入参。而自动装箱则是调用Integer.valueof()方法,当值介于-127到128时,返回的是缓存数组中对应的Integer对象。而不在这个范围是,返回的则是Integer实例化对象。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值