通过字节码分析Java中自动装箱和拆箱是如何实现的
云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!
Java中自动装箱和拆箱
装箱(Boxing),也称为包装(Wrapper),是在对象中放置原语类型(primitive type)的过程,以便原语(primitive)可以作为引用对象使用。
这里的primitive type就是Java里面的基本类型,所有的基本类型都有一个与之对应的类。例如,Integer类对应基本类型int。
通常,这些类称为包装器(wrapper)。这些对象包装器类拥有很明显的名字:Integer、Long、Float、Double、Short、Byte、Character、Void和Boolean(前6个类派生于公共的超类Number)。
对象包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,对象包装器类还是final,因此不能定义它们的子类。
自动装箱是指通过类型转换(隐式或显式)从值类型中获取引用类型,这部分工作是编译器帮我们来完成的。
我们看一个常见的例子,比如我们创建一个int类型的ArrayList(因为ArrayList的泛型是不允许基本类型的,这里只能使用它们包装类),我们给ArrayList添加元素,再从里面获取元素,一般是这么写的:
// int类型的自动装箱和拆箱 ArrayList<Integer> integerArrayList = new ArrayList<>(); integerArrayList.add(1); int i = integerArrayList.get(0);
这里分别触发了自动装箱和自动拆箱,这里的add操作触发了一次自动装箱操作,将int转化为Integer;接着从ArrayList里面获取元素,由于我们的目标变量类型是基本类型int,但获取到的元素类型是Integer,所以编译器在这里帮我们做了拆箱的操作。
通过字节码查看自动装箱和自动拆箱是如何实现的
我们经常说自动装箱、自动拆箱,到底是如何个自动法,我们来一个眼见为实,通过查看java代码生成的字节码来看下编译器对我们的代码做了什么。
查看字节码的方式
这里介绍两种查看字节码的方式:
- 第一种,通过javac和javap查看:先通过javac将.java代码编译成.class字节码,然后通过javap分析字节码。
(base) tinytongtongdeMacBook-Pro% javac TestAutoWrapper.java (base) tinytongtongdeMacBook-Pro% javap -verbose TestAutoWrapper
这样你就能看到你的字节码信息了。
- 第二种,通过IDE插件ASM Bytecode Outline来查看,具体操作方式见插件说明。
查看自动装箱和拆箱的字节码
public static void main(String[] args) { // int类型的自动装箱和拆箱 ArrayList<Integer> integerArrayList = new ArrayList<>(); integerArrayList.add(1);// 自动装箱 int i = integerArrayList.get(0);// 自动拆箱 }
我们生成这段java代码的字节码,核心部分如下:
// access flags 0x9 public static main([Ljava/lang/String;)V ... L1 LINENUMBER 15 L1 ALOAD 1 ICONST_1 INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z POP L2 LINENUMBER 16 L2 ALOAD 1 ICONST_0 INVOKEVIRTUAL java/util/ArrayList.get (I)Ljava/lang/Object; CHECKCAST java/lang/Integer INVOKEVIRTUAL java/lang/Integer.intValue ()I ISTORE 2 ...
L1部分中的倒数第二行,INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z,INVOKEVIRTUAL指令表示一个虚方法调用,这里具体就是我们java代码中的integerArrayList.add(1);,自动装箱发生在哪呢?就在它上面,INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;,INVOKESTATIC表示静态方法调用,这里对应的Java语句就是Integer#valueOf()方法。
接下来我们看下自动装箱对应的字节码,也就是L2部分,先看INVOKEVIRTUAL java/util/ArrayList.get (I)Ljava/lang/Object;,它对应的java代码是integerArrayList.get(0),表示从ArrayList里面获取到Integer类型对象。自动拆箱发生在下面,就是NVOKEVIRTUAL java/lang/Integer.intValue ()I这条指令,它对应的java方法是Integer#intValue()方法。
看到这里相信大家对自动装箱和拆箱有一个比较具体的认识了,说白了就是编译器会根据情况替我们做一些工作,通过插入字节码指令来替我们完成装箱和拆箱操作。int对应的装箱方法是Integer#valueOf,拆箱方法是Integer#intValue()。
自动装箱和拆箱的触发时机
我们接着讲下自动装箱和拆箱的触发时机,具体如下:
* 进行 = 赋值操作(装箱或拆箱) * 进行+,-,*,/混合运算 (拆箱) * 进行>,<,==比较运算(拆箱) * 调用equals进行比较(装箱) * ArrayList,HashMap等集合类 添加基础类型数据时(装箱)
基本类型自动装箱和拆箱方法总结
感兴趣的同学可以自己试下各种操作下,自动装箱和拆箱的表现,查看对应的字节码即可。
【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/live立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK
原文发布时间:2020-08-04
本文作者:tinyvampirepudge
本文来自:“掘金”,了解相关信息可以关注“掘金”

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
大量承载“新基建”的基础设施,共享模式的“数字孪生”来了
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 你好,这是我在【物女心经】专栏写的第190篇文章。 在7月30日召开的中共中央政治局会议中,再次强调要加快新型基础设施建设,深入推进重大区域发展战略,加快国家重大战略项目实施步伐。新基建的意义在于,促进中国的产业链升级,加快新技术、新产品的爆发和新业务模式的诞生。 在新基建中,隐含着一些相通的底层基础设施,数字孪生就是其中之一。它并不是一个新生事物,研究机构Gartner已经连续3年将其评为全球十大科技趋势之一;另一家研究公司Markets & Markets则预测认为,由其所撬动的市场,有可能呈现指数级增长,在未来5年增长10倍,从每年的38亿美元增长到358亿美元。 到底什么是数字孪生? 根据广泛采用的定义,数字孪生是物理实体的数字化镜像。 数字孪生通过将物体、系统、流程的信息,利用数字技术实时映射在数字化系统中,对产品、制造过程乃至整个工厂进行虚拟仿真,从而让企业实时了解资产的状态、响应变化,改善业务运营,创造新的价值。 数字孪生为什么重要? 数位孪生是推动产品创新与性能提...
- 下一篇
面试官:你简历上有熟悉设计模式,那你给我说一下单例模式实现及线程安全吧
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 前言 单例应用的太广泛,大家应该都用过,本文主要是想聊聊线程安全的单例以及反序列化破坏单例的情况。 1、概念 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 关键点: 私有化构造函数 通过一个静态方法或枚举返回单例类对象 确保单例类的对象有且只有一个,尤其是多线程环境下 确保单例类对象在反序列化时不会重新构建对象 2、实现 2.1、线程安全的单例 2.1.2、饿汉模式 饿汉模式:不管有没有调用getInstance方法,只要类加载了,我就给你new出来(a) public class A { private static final A a = new A(); public static A getInstance() { return a; } private A() {} } 以下两点保证了以上代码的线程安全: 调用一个类的静态方法的时候会触发类的加载(如果类没加载过) 类只会加载(被加载到虚拟机内存的过程,包括5个阶段)一次 static变量在类初始化的时候(...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装